PHP擴(kuò)展之壓縮與歸檔擴(kuò)展2——Phar
Phar 歸檔的概念來(lái)自 Java? 技術(shù)的 JAR 歸檔,它允許使用單個(gè)文件打包應(yīng)用程序,這個(gè)文件中包含運(yùn)行應(yīng)用程序所需的所有東西。該文件不同于單個(gè)可執(zhí)行文件,后者通常由編程語(yǔ)言生成,比如 C,因?yàn)樵撐募?shí)際上是一個(gè)歸檔文件而非編譯過(guò)的應(yīng)用程序。因此 JAR 文件實(shí)際上包含組成應(yīng)用程序的文件,但是考慮到安全性,不對(duì)這些文件進(jìn)行仔細(xì)區(qū)分。Phar 擴(kuò)展正是基于類似的理念,但是在設(shè)計(jì)時(shí)主要針對(duì) PHP 的 Web 環(huán)境。同樣,與 JAR 歸檔不同的是,Phar 歸檔可由 PHP 本身處理,因此不需要使用額外的工具來(lái)創(chuàng)建或使用。
Phar 擴(kuò)展對(duì) PHP 來(lái)說(shuō)并不是一個(gè)新鮮的概念。它最初使用 PHP 編寫并被命名為 PHP_Archive,然后在 2005 年被添加到 PEAR 庫(kù)。然而在實(shí)際中,解決這一問(wèn)題的純 PHP 解決方案非常緩慢,因此 2007 年重新編寫為純 C 語(yǔ)言擴(kuò)展,同時(shí)添加了使用 SPL 的ArrayAccess?對(duì)象遍歷 Phar 歸檔的支持。自那時(shí)起,人們做了大量工作來(lái)改善 Phar 歸檔的性能。
創(chuàng)建 Phar創(chuàng)建 Phar 文件需要執(zhí)行若干步驟。所有步驟需要用到某種形式的 PHP 命令完成創(chuàng)建,因?yàn)椴淮嬖谟糜趧?chuàng)建歸檔的獨(dú)立工具。此外,要?jiǎng)?chuàng)建和修改 Phar 文件,php.ini 設(shè)置 phar.readonly 必須被設(shè)置為 0。在 PHP 的 Phar 歸檔內(nèi)打開和引用文件時(shí)不需要使用到該設(shè)置。
讓我們看一看創(chuàng)建可用于驅(qū)動(dòng)應(yīng)用程序的 Phar 文件需要哪些步驟。應(yīng)用程序的設(shè)計(jì)目標(biāo)是從 Web 瀏覽器或命令提示符直接加載。第一步是創(chuàng)建 Phar 文件,因此我們將創(chuàng)建清單 1 所示的?Phar?對(duì)象。對(duì)象引用將允許您控制 Phar 歸檔的所有方面。
示例 1. 創(chuàng)建?Phar?對(duì)象
$p = new Phar(’/path/to/my.phar’, CURRENT_AS_FILEINFO | KEY_AS_FILENAME, ’my.phar’);$p->startBuffering();
構(gòu)造函數(shù)的第一個(gè)參數(shù)表示保存 Phar 文件的位置。第二個(gè)參數(shù)將所有參數(shù)都傳遞給?RecursiveDirectoryIterator?父類。第三個(gè)參數(shù)是在流上下文中引用 Phar 歸檔的別名。因此對(duì)于清單 1,可以在這個(gè) Phar 歸檔中使用 phar://my.phar 引用文件。您還可以發(fā)出Phar::startBuffering()?方法調(diào)用來(lái)緩沖對(duì)歸檔做出的修改,直到發(fā)出?Phar::stopBuffering()?命令為止。盡管不一定要執(zhí)行上述操作,但是這樣做確實(shí)改善了創(chuàng)建或修改歸檔的性能,因?yàn)樗苊饬嗣看卧谀_本中修改歸檔時(shí)對(duì)做出的修改進(jìn)行保存。
默認(rèn)情況下,創(chuàng)建的 Phar 將使用原生的基于 Phar 的歸檔格式。還可以按照清單 2 所示將格式轉(zhuǎn)換為 ZIP 格式,從而對(duì) Phar 文件使用 ZIP 或 TAR 格式。示例 2. 將存儲(chǔ)格式轉(zhuǎn)換為 ZIP 格式
$p = $p->convertToExecutable(Phar::ZIP);
轉(zhuǎn)換歸檔格式有利也有弊。主要優(yōu)點(diǎn)就是能夠使用任何處理 ZIP 或 TAR 文件的工具查看歸檔的內(nèi)容。然而,如果 Phar 歸檔沒有使用原生的基于 Phar 的歸檔格式,那么它不需要使用 Phar 擴(kuò)展加載歸檔,而使用 ZIP 或 TAR 格式的 Phar 歸檔則需要如此。
接下來(lái),將需要定義文件存根(stub),這是在加載 Phar 文件時(shí)首先調(diào)用的代碼。
Phar 文件存根文件存根僅僅是在加載 Phar 文件時(shí)最初運(yùn)行的代碼的一小部分,并且始終以一個(gè)?__HALT_COMPILER()?標(biāo)記作為結(jié)束。清單 3 展示了一個(gè)典型的文件存根。示例 3. Phar 文件存根
<?php Phar::mapPhar(); include ’phar://myphar.phar/index.php’; __HALT_COMPILER();
上面所示的?Phar::mapPhar()?方法調(diào)用通過(guò)讀取清單文件(manifest)對(duì) Phar 歸檔執(zhí)行初始化。您需要在歸檔內(nèi)引用文件之前使用 phar:// 流包裝器執(zhí)行初始化。初始加載的文件將是應(yīng)用程序首次加載時(shí)的文件;在本例中為 index.php。
如何將這個(gè)文件存根 Phar 添加到 Phar 歸檔取決于所使用的歸檔的格式。對(duì)于基于 Phar 的歸檔,使用?Phar::setStub()?方法,它將接受 PHP 代碼的惟一參數(shù),并以字符串形式放入存根中。清單 4 演示了這一方法。示例 4. 使用?Phar::setStub()?創(chuàng)建文件存根
$p->setStub(’<?php Phar::mapPhar(); include ’phar://myphar.phar/index.php’; __HALT_COMPILER(); ?>’);
如果您計(jì)劃使用存根而不是重定向到 index.php 頁(yè)面來(lái)完成操作,可以使用 helper 方法?Phar::createDefaultStub()?構(gòu)建文件存根。因此,只需要傳遞您希望包含在文件存根的文件的名稱。在清單 5 中,將重寫?Phar::setStub()?方法調(diào)用來(lái)使用 helper 方法。
示例 5. 使用?Phar::createDefaultStub()?創(chuàng)建文件存根
$p->setStub($p-> createDefaultStub(’index.php’));
如果從 Web 服務(wù)器加載 Phar,Phar::createDefaultStub()?方法的第二個(gè)可選參數(shù)允許包含一個(gè)不同的文件。這對(duì)于設(shè)計(jì)用于命令行或 Web 瀏覽器上下文的應(yīng)用程序非常方便。
對(duì)于基于 ZIP 和 TAR 的實(shí)現(xiàn),將以上存根的內(nèi)容存儲(chǔ)到 .phar/stub.php 文件內(nèi),而不是使用?setStub()?命令。
將文件添加到歸檔Phar?對(duì)象使用?ArrayAccess?SPL 對(duì)象,允許以數(shù)組的形式訪問(wèn)歸檔內(nèi)容,因此提供了許多方法來(lái)向歸檔添加文件。最簡(jiǎn)單的方法是直接使用?ArrayAccess?接口。示例 6. 向歸檔添加文件
$p[’file.txt’] = ’This is a text file’;$p[’index.php’] = file_get_contents(’index.php’);
示例 6 表明文件名被指定為數(shù)組鍵,將內(nèi)容指定為值。可以使用?file_get_contents()?函數(shù)獲得現(xiàn)有文件的內(nèi)容,然后將內(nèi)容設(shè)為值。這樣可以更加靈活地向歸檔添加文件,可以通過(guò)引用現(xiàn)有文件或動(dòng)態(tài)構(gòu)建文件實(shí)現(xiàn)。后一種方法可以作為應(yīng)用程序構(gòu)建腳本的一部分。
如果存儲(chǔ)在 Phar 歸檔中的文件非常大,可以分別通過(guò)?PharFileInfo::setCompressedGZ()?或PharFileInfo::setCompressedBZIP2()?方法使用 gzip 或 bzip2 壓縮有選擇地壓縮歸檔中的文件。在清單 7 中,您將使用 bzip2 壓縮文件。示例 7. 使用 bzip2 壓縮 Phar 歸檔中的文件
$p[’big.txt’] = ’This is a big text file’;$p[’big.txt’]->setCompressedBZIP2();
要壓縮文件或使用包含壓縮文件的歸檔,必須在 PHP 安裝中支持 bzip2 或 zlib(用于 gz 壓縮文件)擴(kuò)展。
假設(shè)您需要將許多文件加入到歸檔中。使用?ArrayAccess?接口逐一添加文件是一項(xiàng)非常單調(diào)的工作,因此可以使用一些便捷的方法。一種方法就是使用?Phar::buildFromDirectory()?方法,該方法將遍歷指定的目錄并添加其中的文件。它還支持對(duì)添加的文件進(jìn)行過(guò)濾,方法是使用文件的正則表達(dá)式模式傳遞第二個(gè)參數(shù),以匹配文件并添加到歸檔中。清單 8 展示了這一過(guò)程。示例 8. 使用?Phar::buildFromDirectory()?向歸檔添加文件
$p->buildFromDirectory(’/path/to/files’,’./.php$/’);
示例 8 將指定目錄中的 PHP 文件添加到 Phar 歸檔。如果需要對(duì)添加的文件執(zhí)行任何修改,比如將文件壓縮,那么可以使用ArrayAccess?接口返回。
可以使用一個(gè)迭代器(iterator)通過(guò)?Phar::buildFromIterator()?方法添加文件。支持兩種風(fēng)格的迭代器:一種是將 Phar 中的文件名映射到磁盤文件的名稱,另一種是返回?SplFileInfo?對(duì)象。RecursiveDirectoryIterator?是一種兼容的迭代器,下面展示如何使用它向歸檔添加目錄文件。示例 9. 使用?Phar::buildFromIterator()?向歸檔添加目錄文件
$p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(’/path/to/files’)),’/path/to/files’);
Phar::buildFromIterator()?方法接受迭代器對(duì)象本身作為惟一的參數(shù)。在上例中,您已經(jīng)使用RecursiveIteratorIterator?對(duì)象包裝了?RecursiveDirectoryIterator?對(duì)象,RecursiveIteratorIterator?對(duì)象提供了Phar::buildFromIterator()?方法所需的兼容型迭代器。
我們現(xiàn)在已經(jīng)創(chuàng)建了一個(gè) Phar 歸檔,它可以用于任何 PHP 應(yīng)用程序。讓我們看一看如何方便地使用這個(gè)歸檔。
使用 Phar 歸檔Phar 歸檔的一個(gè)優(yōu)點(diǎn)就是可以非常方便地集成到任何應(yīng)用程序中。如果使用的是原生的基于 Phar 的歸檔格式,這一點(diǎn)尤其明顯。在這種情況下,您甚至不需要安裝 Phar 擴(kuò)展,因?yàn)?PHP 天生就可以加載文件并提取文件內(nèi)容。基于 ZIP 和 TAR 的歸檔需要加載 Phar 擴(kuò)展。
Phar 歸檔在設(shè)計(jì)時(shí)被包括到應(yīng)用程序中,跟普通的 PHP 文件一樣,這使得已經(jīng)熟悉如何包含其他第三方代碼的應(yīng)用程序開發(fā)人員可以非常方便地使用 Phar 歸檔。讓我們看一看在應(yīng)用程序中集成 Phar 有多么容易。
在應(yīng)用程序中集成 Phar 歸檔代碼
在 Phar 歸檔中集成代碼的最簡(jiǎn)單方法就是包含 Phar 歸檔,然后在 Phar 文件中包含需要使用的文件。phar:// 流包裝器可以用來(lái)訪問(wèn)已加載 Phar 歸檔中的文件,如下所示。示例 10. 在 Phar 歸檔中加載代碼
include ’myphar.phar’; include ’phar://myphar.phar/file.php’;
第一個(gè) include 將加載 myphar.phar 歸檔,包含文件存根中指定的代碼。第二個(gè) include 使用流包裝器打開 Phar 歸檔并且僅在歸檔中包括指定的文件。注意在歸檔中包含文件之前,您不需要包含 Phar 歸檔本身,如清單 10 所示。
從 Phar 歸檔運(yùn)行 PHP 應(yīng)用程序Phar 歸檔的一個(gè)出色特性就是可以使用一個(gè) Phar 歸檔打包整個(gè)應(yīng)用程序并進(jìn)行發(fā)布。這種方法的優(yōu)點(diǎn)就是簡(jiǎn)化應(yīng)用程序部署并且不會(huì)降低性能,它主要得益于 PHP V5.3 中新增的若干 Phar 增強(qiáng)。然而,設(shè)計(jì)在 Phar 中運(yùn)行的應(yīng)用程序時(shí)應(yīng)當(dāng)考慮以下幾點(diǎn):
任何需要?jiǎng)?chuàng)建的特定于應(yīng)用程序?qū)嵗奈募热?config 文件,都不能作為歸檔的一部分,因此需要將它們寫入到獨(dú)立但是可訪問(wèn)的位置。如果應(yīng)用程序創(chuàng)建構(gòu)成擴(kuò)展的緩存文件,那么這些文件也要采用相同的做法。您應(yīng)當(dāng)始終使用基于 Phar 的歸檔格式,并且不對(duì)歸檔中的文件進(jìn)行壓縮,從而獲得最大的靈活性。基于 ZIP 和 TAR 的歸檔要求在 PHP 中安裝 Phar 擴(kuò)展,而基于 Phar 的歸檔甚至可用于未安裝 Phar 擴(kuò)展的情況。應(yīng)用程序中的任何文件引用都需要修改為同時(shí)使用 phar:// 流包裝器和歸檔名,如前面小節(jié)所示。PHPMyAdmin 是一種流行的 PHP 應(yīng)用程序,它一直使用 Phar 打包,演示出使用 Phar 歸檔的簡(jiǎn)便性。它一直以來(lái)被設(shè)計(jì)為從 Phar 歸檔文件運(yùn)行,但是仍然能夠在 Phar 歸檔之外存儲(chǔ)配置文件。
相關(guān)文章:
1. 使用css實(shí)現(xiàn)全兼容tooltip提示框2. SharePoint Server 2019新特性介紹3. 告別AJAX實(shí)現(xiàn)無(wú)刷新提交表單4. CSS3實(shí)例分享之多重背景的實(shí)現(xiàn)(Multiple backgrounds)5. ASP中常用的22個(gè)FSO文件操作函數(shù)整理6. XML入門的常見問(wèn)題(四)7. 詳解盒子端CSS動(dòng)畫性能提升8. Vue+elementUI下拉框自定義顏色選擇器方式9. XML入門的常見問(wèn)題(一)10. css進(jìn)階學(xué)習(xí) 選擇符
