首頁 後端開發 php教程 PHP壓縮與歸檔—Phar

PHP壓縮與歸檔—Phar

Nov 22, 2016 am 09:45 AM

Phar 歸檔的概念來自 Java™ 技術的 JAR 歸檔,它允許使用單一檔案打包應用程序,這個檔案中包含運行應用程式所需的所有東西。該文件不同於單一可執行文件,後者通常由程式語言生成,例如 C,因為該文件實際上是歸檔文件而非編譯過的應用程式。因此 JAR 文件實際上包含組成應用程式的文件,但是考慮到安全性,不會仔細區分這些文件。 Phar 擴充正是基於類似的理念,但在設計時主要針對 PHP 的 Web 環境。同樣,與 JAR 歸檔不同的是,Phar 歸檔可由 PHP 本身處理,因此不需要使用額外的工具來建立或使用。

Phar 擴充對 PHP 來說並不是一個新鮮的概念。它最初使用 PHP 編寫並被命名為 PHP_Archive,然後在 2005 年被添加到 PEAR 庫。然而在實際中,解決這一問題的純 PHP 解決方案非常緩慢,因此 2007 年重新編寫為純 C 語言擴展,同時添加了使用 SPL 的ArrayAccess 物件遍歷 Phar 歸檔的支援。自那時起,人們做了大量工作來改善 Phar 歸檔的表現。

建立 Phar

建立 Phar 檔案需要執行若干步驟。所有步驟需要用到某種形式的 PHP 指令完成創建,因為不存在用來建立歸檔的獨立工具。此外,要建立和修改 Phar 文件,php.ini 設定 phar.readonly 必須被設定為 0。在 PHP 的 Phar 歸檔內開啟和引用檔案時不需要使用到該設定。

讓我們來看看建立可用於驅動應用程式的 Phar 檔案需要哪些步驟。應用程式的設計目標是從 Web 瀏覽器或命令提示字元直接載入。第一步是建立 Phar 文件,因此我們將建立清單 1 所示的 Phar 物件。物件參考將允許您控制 Phar 歸檔的所有方面。

範例 1. 建立 Phar 物件

$p = new Phar('/path/to/my.phar', CURRENT_AS_FILEINFO | KEY_AS_FILENAME, 'my.phar');
$p->startBuffering();
登入後複製

    構造函數的第一個參數表示儲存 Phar 檔案的位置。第二個參數將所有參數都傳遞給 RecursiveDirectoryIterator 父類別。第三個參數是在流上下文中引用 Phar 歸檔的別名。因此對於清單 1,可以在這個 Phar 歸檔中使用 phar://my.phar 引用文件。您也可以發出Phar::startBuffering() 方法呼叫來緩衝歸檔所做的修改,直到發出 Phar::stopBuffering() 指令為止。儘管不一定要執行上述操作,但是這樣做確實改善了創建或修改歸檔的效能,因為它避免了每次在腳本中修改歸檔時對所做的修改進行保存。

預設情況下,建立的 Phar 將使用原生的基於 Phar 的歸檔格式。也可以依照清單 2 所示將格式轉換為 ZIP 格式,從而對 Phar 檔案使用 ZIP 或 TAR 格式。
範例 2. 將儲存格式轉換為 ZIP 格式

$p = $p->convertToExecutable(Phar::ZIP);
登入後複製


 轉換歸檔格式有利也有弊。主要優點就是能夠使用任何處理 ZIP 或 TAR 檔案的工具來檢視歸檔的內容。然而,如果 Phar 歸檔沒有使用原生的基於 Phar 的歸檔格式,那麼它不需要使用 Phar 擴充來載入歸檔,而使用 ZIP 或 TAR 格式的 Phar 歸檔則需要如此。

接下來,將需要定義檔案存根(stub),這是在載入 Phar 檔案時首先呼叫的程式碼。

Phar 檔案存根

文件存根只是在載入 Phar 檔案時最初執行的程式碼的一小部分,並且總是以一個 __HALT_COMPILER() 標記作為結束。清單 3 展示了一個典型的文件存根。
範例 3. Phar 檔案存根

<?php
    Phar::mapPhar();
    include &#39;phar://myphar.phar/index.php&#39;;
    __HALT_COMPILER();
登入後複製

上面所示的 Phar::mapPhar() 方法呼叫透過讀取清單檔案(manifest)對 Phar 歸檔執行初始化。您需要在歸檔內引用檔案之前使用 phar:// 流包裝器執行初始化。初始載入的檔案將是應用程式首次載入時的檔案;在本例中為 index.php。

如何將這個文件存根 Phar 加到 Phar 歸檔取決於所使用的歸檔的格式。對於基於 Phar 的歸檔,使用 Phar::setStub() 方法,它將接受 PHP 程式碼的惟一參數,並以字串形式放入存根中。清單 4 示範了這個方法。
範例 4. 使用 Phar::setStub() 建立檔案存根

$p->setStub(&#39;<?php Phar::mapPhar(); 
include &#39;phar://myphar.phar/index.php&#39;; __HALT_COMPILER(); ?>&#39;);
登入後複製

如果您打算使用存根而不是重定向到 index.php 頁面來完成操作,可以使用 helper 方法 Phar::createDefaultStub() 建立檔案存根。因此,只需要傳遞您希望包含在文件存根中的文件的名稱。在清單 5 中,將重寫 Phar::setStub() 方法呼叫來使用 helper 方法。

範例 5. 使用 Phar::createDefaultStub() 建立檔案存根

$p->setStub($p-> createDefaultStub(&#39;index.php&#39;));
登入後複製


如果从 Web 服务器加载 Phar,Phar::createDefaultStub() 方法的第二个可选参数允许包含一个不同的文件。这对于设计用于命令行或 Web 浏览器上下文的应用程序非常方便。

对于基于 ZIP 和 TAR 的实现,将以上存根的内容存储到 .phar/stub.php 文件内,而不是使用 setStub() 命令。

将文件添加到归档

Phar 对象使用 ArrayAccess SPL 对象,允许以数组的形式访问归档内容,因此提供了许多方法来向归档添加文件。最简单的方法是直接使用 ArrayAccess 接口。
示例 6. 向归档添加文件

$p[&#39;file.txt&#39;] = &#39;This is a text file&#39;;
$p[&#39;index.php&#39;] = file_get_contents(&#39;index.php&#39;);
登入後複製

示例 6 表明文件名被指定为数组键,将内容指定为值。可以使用 file_get_contents() 函数获得现有文件的内容,然后将内容设为值。这样可以更加灵活地向归档添加文件,可以通过引用现有文件或动态构建文件实现。后一种方法可以作为应用程序构建脚本的一部分。

如果存储在 Phar 归档中的文件非常大,可以分别通过 PharFileInfo::setCompressedGZ() 或PharFileInfo::setCompressedBZIP2() 方法使用 gzip 或 bzip2 压缩有选择地压缩归档中的文件。在清单 7 中,您将使用 bzip2 压缩文件。
示例 7. 使用 bzip2 压缩 Phar 归档中的文件

$p[&#39;big.txt&#39;] = &#39;This is a big text file&#39;;
$p[&#39;big.txt&#39;]->setCompressedBZIP2();
登入後複製

要压缩文件或使用包含压缩文件的归档,必须在 PHP 安装中支持 bzip2 或 zlib(用于 gz 压缩文件)扩展。

假设您需要将许多文件加入到归档中。使用 ArrayAccess 接口逐一添加文件是一项非常单调的工作,因此可以使用一些便捷的方法。一种方法就是使用 Phar::buildFromDirectory() 方法,该方法将遍历指定的目录并添加其中的文件。它还支持对添加的文件进行过滤,方法是使用文件的正则表达式模式传递第二个参数,以匹配文件并添加到归档中。清单 8 展示了这一过程。
示例 8. 使用 Phar::buildFromDirectory() 向归档添加文件

$p->buildFromDirectory(&#39;/path/to/files&#39;,&#39;./\.php$/&#39;);
登入後複製


示例 8 将指定目录中的 PHP 文件添加到 Phar 归档。如果需要对添加的文件执行任何修改,比如将文件压缩,那么可以使用ArrayAccess 接口返回。

可以使用一个迭代器(iterator)通过 Phar::buildFromIterator() 方法添加文件。支持两种风格的迭代器:一种是将 Phar 中的文件名映射到磁盘文件的名称,另一种是返回 SplFileInfo 对象。RecursiveDirectoryIterator 是一种兼容的迭代器,下面展示如何使用它向归档添加目录文件。
示例 9. 使用 Phar::buildFromIterator() 向归档添加目录文件

$p->buildFromIterator(new RecursiveIteratorIterator
(new RecursiveDirectoryIterator(&#39;/path/to/files&#39;)),&#39;/path/to/files&#39;);
登入後複製

Phar::buildFromIterator() 方法接受迭代器对象本身作为惟一的参数。在上例中,您已经使用RecursiveIteratorIterator 对象包装了 RecursiveDirectoryIterator 对象,RecursiveIteratorIterator 对象提供了Phar::buildFromIterator() 方法所需的兼容型迭代器。

我们现在已经创建了一个 Phar 归档,它可以用于任何 PHP 应用程序。让我们看一看如何方便地使用这个归档。

使用 Phar 归档

Phar 归档的一个优点就是可以非常方便地集成到任何应用程序中。如果使用的是原生的基于 Phar 的归档格式,这一点尤其明显。在这种情况下,您甚至不需要安装 Phar 扩展,因为 PHP 天生就可以加载文件并提取文件内容。基于 ZIP 和 TAR 的归档需要加载 Phar 扩展。

Phar 归档在设计时被包括到应用程序中,跟普通的 PHP 文件一样,这使得已经熟悉如何包含其他第三方代码的应用程序开发人员可以非常方便地使用 Phar 归档。让我们看一看在应用程序中集成 Phar 有多么容易。

在应用程序中集成 Phar 归档代码

在 Phar 归档中集成代码的最简单方法就是包含 Phar 归档,然后在 Phar 文件中包含需要使用的文件。phar:// 流包装器可以用来访问已加载 Phar 归档中的文件,如下所示。
示例 10. 在 Phar 归档中加载代码

include &#39;myphar.phar&#39;;  
include &#39;phar://myphar.phar/file.php&#39;;
登入後複製

    第一个 include 将加载 myphar.phar 归档,包含文件存根中指定的代码。第二个 include 使用流包装器打开 Phar 归档并且仅在归档中包括指定的文件。注意在归档中包含文件之前,您不需要包含 Phar 归档本身,如清单 10 所示。

从 Phar 归档运行 PHP 应用程序

Phar 歸檔的一個出色特性就是可以使用一個 Phar 歸檔打包整個應用程式並進行發布。這種方法的優點就是簡化應用程式部署並且不會降低效能,它主要得益於 PHP V5.3 中新增的若干 Phar 增強。然而,設計在Phar 中運行的應用程式時應考慮以下幾點:

任何需要創建的特定於應用程式實例的文件,例如config 文件,都不能作為歸檔的一部分,因此需要將它們寫入獨立但是可訪問的位置。如果應用程式建立構成擴充功能的快取文件,那麼這些文件也要採用相同的做法。

您應始終使用基於 Phar 的歸檔格式,並且不對歸檔中的檔案進行壓縮,從而獲得最大的靈活性。基於 ZIP 和 TAR 的歸檔要求在 PHP 中安裝 Phar 擴展,而基於 Phar 的歸檔甚至可用於未安裝 Phar 擴展的情況。

應用程式中的任何檔案引用都需要修改為同時使用 phar:// 流包裝器和歸檔名,如前面小節所示。

PHPMyAdmin 是一種流行的 PHP 應用程序,它一直使用 Phar 打包,演示出使用 Phar 歸檔的簡便性。它一直以來被設計為從 Phar 歸檔文件運行,但是仍然能夠在 Phar 歸檔之外存儲配置文件。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1663
14
CakePHP 教程
1420
52
Laravel 教程
1313
25
PHP教程
1266
29
C# 教程
1239
24
說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 Apr 08, 2025 am 12:03 AM

PHP中有四種主要錯誤類型:1.Notice:最輕微,不會中斷程序,如訪問未定義變量;2.Warning:比Notice嚴重,不會終止程序,如包含不存在文件;3.FatalError:最嚴重,會終止程序,如調用不存在函數;4.ParseError:語法錯誤,會阻止程序執行,如忘記添加結束標籤。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? 什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? Apr 09, 2025 am 12:09 AM

HTTP請求方法包括GET、POST、PUT和DELETE,分別用於獲取、提交、更新和刪除資源。 1.GET方法用於獲取資源,適用於讀取操作。 2.POST方法用於提交數據,常用於創建新資源。 3.PUT方法用於更新資源,適用於完整更新。 4.DELETE方法用於刪除資源,適用於刪除操作。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

解釋self ::,parent ::和static :: in php oop中的區別。 解釋self ::,parent ::和static :: in php oop中的區別。 Apr 09, 2025 am 12:04 AM

在PHPOOP中,self::引用當前類,parent::引用父類,static::用於晚靜態綁定。 1.self::用於靜態方法和常量調用,但不支持晚靜態綁定。 2.parent::用於子類調用父類方法,無法訪問私有方法。 3.static::支持晚靜態綁定,適用於繼承和多態,但可能影響代碼可讀性。

PHP如何安全地上載文件? PHP如何安全地上載文件? Apr 10, 2025 am 09:37 AM

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

See all articles