什么是composer
在之前的PHP開發(fā)中水慨,我也僅僅是使用composer來進行依賴的管理败匹,沒有深度去理解到底什么是composer,今天有時間就開始深入的研究一下讥巡。
Composer 不是一個包管理器掀亩。是的,它涉及 "packages" 和 "libraries"欢顷,但它在每個項目的基礎(chǔ)上進行管理槽棍,在你項目的某個目錄中(例如 vendor)進行安裝。默認情況下它不會在全局安裝任何東西抬驴。因此炼七,這僅僅是一個依賴管理。 --來自composer的官方文檔
其實上面的文案在一開始接觸composer的時候我是能明白他說什么的布持,但是今天仔細分析又發(fā)現(xiàn)對其中的很多表述還是比較模糊豌拙。首先是包管理器的理解。
包管理器又稱軟件包管理系統(tǒng)题暖,它是在電腦中自動安裝按傅、配制捉超、卸載和升級軟件包的工具組合,在各種系統(tǒng)軟件和應用軟件的安裝管理中均有廣泛應用唯绍。 --百度百科
軟件包(SoftWare Package)是指具有特定的功能拼岳,用來完成特定任務的一個程序或一組程序】雒ⅲ可分為應用軟件包和系統(tǒng)軟件包兩大類惜纸。應用軟件包與特定的應用領(lǐng)域有關(guān),又可分為通用包及專用包兩類绝骚。通用軟件包根據(jù)社會的一些共同需求開發(fā)耐版,專用軟件包則是生產(chǎn)者根據(jù)用戶的具體需求定制的,可以為適合其特殊需要進行修改或變更
通過軟件包管理器能理解压汪,包管理器更多的管理的能直接執(zhí)行的應用程序椭更,像rpm,apt蛾魄,brew虑瀑,yum都是指定的類Unix系統(tǒng)的包管理器。而對于PHP腳本語言滴须,在開發(fā)者編寫的腳本 一般依賴的是各種庫的腳本舌狗。所以在composer定義中先說明composer不是一個包管理器。
終于后面它涉及 "packages" 和 "libraries" 扔水,我一直想接著查詢 "packages" 和 "libraries"區(qū)別痛侍,但是沒有找到相關(guān)描述。但是定義最后一句明確說明了魔市,他是一個依賴管理工具主届。
phar 文件
在我們下載composer的時候都可以看到是下載一個composer.phar 文件。那么phar 文件是什么類型的文件待德,他和PHP的關(guān)系是什么君丁?所以要深入了解composer應該先從phar開始
phar打包PHP程序
PHAR (“Php ARchive”) 是PHP里類似于JAR的一種打包文件。如果你使用的是 PHP 5.3 或更高版本将宪,那么Phar后綴文件是默認開啟支持的绘闷,你不需要任何其他的安裝就可以使用它。phar歸檔文件有三種格式:tar歸檔较坛、zip歸檔印蔗、phar歸檔,前兩種執(zhí)行需要php安裝Phar 擴展支持丑勤,用的也比較少华嘹,這里主要講phar歸檔格式。
- 我們?yōu)槭裁葱枰猵har呢法竞,是因為PHP的腳本語言的特性耙厚,如果你開發(fā)的一個項目擔心在部署的時候被修改强挫,那么可以通過將項目中的多個文件打包成一個文件,并且這個文件默認是只讀的方式颜曾。這樣就可以封裝上線了。
- 簡單的理解一下:項目文件的打包可以通過zip秉剑,tar泛豪,只不過phar打包后的文件不需要顯示的再解壓,可以直接被PHP使用侦鹏。
Rather than using the ZIP file format the simpler tar format was used, and the first PHAR was created using the tar command line utility[1] as a proof of concept. On June 14, 2004[2] the initial PHP_Archive package was proposed to PEAR and on December 13, 2004 it was accepted unanimously.[3] 來自 wiki百科
可以看到第一個phar就是tar格式打包的文件诡曙,而且是直接用tar命令行工具生成。
phar 文件是文本文件還是二進制
通過上文的理解略水,既然我們將項目文件整合到一個文件了价卤,所以理所當然的就會考慮重寫整理文件格式以達到節(jié)省空間提高效率的目的。所以打包后的phar是一個二進制文件(想想第一個tar打包的phar文件)渊涝。 只不過隨后phar開始自己的打包的文件格式慎璧。下圖是phar打包文件格式。
phar 文件是支持權(quán)限和分組的跨释。
The Phar manifest is a highly optimized format that allows per-file specification of file compression, file permissions, and even user-defined meta-data such as file user or group. All values greater than 1 byte are stored in little-endian byte order, with the exception of the API version, which for historical reasons is stored as 3 nibbles in big-endian order.
phar 日常使用例子
新建項目目錄如下
其中的 build 目錄里將放置 PHAR 文件胸私,這樣能避免它跟源碼程序混合到一起。src 放的就是我們的PHP源碼鳖谈。
index.php 會成為我們的應用的入口程序岁疼,common.php 可以放置應用需要的一些共有代碼,config.ini 是我們的配置文件缆娃。
index.php 大概是這樣樣子:
<?php
require_once "phar://myapp.phar/common.php";
$config = parse_ini_file("config.ini");
AppManager::run($config);
common.php 大概是這樣的:
<?php
class AppManager
{
public static function run($config) {
echo "Application is now running with the following configuration... ";
var_dump($config);
}
}
在我們的PHP應用目錄里捷绒,需要有一個創(chuàng)建Phar文件的腳本,我們給它起名叫 create-phar.php贯要,放置到 myapp 的跟目錄下暖侨,里面添加如下代碼:
<?php
/**
* 目的 :將PHP框架項目,打包成一個 .phar 文件
* 常用 :這個打包崇渗,一般是用PHP語言來做 linux 系統(tǒng)軟件的它碎,如composer.phar
*
*
* 方法:
*
* 壓縮myaoo 目錄下的(php,可選)文件
*
* 1、將 php.ini 的 `;phar.readonly = On` 改為 `phar.readonly = Off`
*
* 2显押、運行 create-phar.php(本文件)扳肛,會在當前目錄下生成 myapp.phar
*
* 3、在git-bash里乘碑,運行 php ./myapp.phar
*
* 4挖息、在git-bash里(網(wǎng)頁也可以),運行php ./myapp/index.php兽肤。輸出結(jié)果 等同于 第3步輸出結(jié)果
*/
## 壓縮的包名
$phar = new Phar($buildRoot . "/myapp.phar",
FilesystemIterator::CURRENT_AS_FILEINFO |
FilesystemIterator::KEY_AS_FILENAME, "myapp.phar");
// 可以簡寫 $phar = new Phar('myphar.phar');
## 壓縮的路徑 【可選參數(shù)套腹,壓縮文件類型】
/*
$phar["index.php"] = file_get_contents($srcRoot . "/index.php");
$phar["common.php"] = file_get_contents($srcRoot . "/common.php");
*/
$phar->buildFromDirectory(__DIR__ . '/myphar', '/\.php$/');
## 壓縮方式绪抛,這里用 gzip 方式
$phar->compressFiles(Phar::GZ);
$phar->stopBuffering();
## 默認自動加載 test_phar 目錄下的哪個文件。| 等同于 nginx 配置 sever {listen 80; …… index index.php; }
$phar->setStub($phar->createDefaultStub('index.php'));
一個新 Phar 對象的創(chuàng)建通常需要三個參數(shù)电禀。第一個參數(shù)是Phar文件的路徑幢码。你不僅可以通過它創(chuàng)建Phar文件,還可以對現(xiàn)存的Phar文件進行操作尖飞。
第二個參數(shù)是設(shè)定 Phar 對象如何處理文件症副。Phar 對象繼承了 PHP RecursiveDirectoryIterator 對象,這個參數(shù)是直接傳遞到父類里政基。這里提供的值是RecursiveDirectoryIterator 的缺省值贞铣,能滿足目前的要求。
第三個參數(shù)是Phar文件的別名沮明,在內(nèi)部引用這個Phar文件時都要使用這個別名辕坝。也就是說,Phar內(nèi)部文件的相互include都需要顯式的使用這個別名荐健。例如酱畅,之前的index.php 對 common.php 的引用就是這種方式。
在Phar對象創(chuàng)建之后江场, index.php 和 common.php 就被加入了Phar文件里了圣贸。Phar 對象是一個數(shù)組,file_get_contents() 方法將各個文件的內(nèi)容讀到數(shù)組里扛稽。你可以向里面添加很多的文件吁峻,但如果你考慮添加大量的文件,比如說整個目錄下的文件在张,你可以考慮使用更方便的 buildFromDirectory() 方法用含。
打開命令行窗口,切換到 myapp 目錄下帮匾,運行命令:
aabouzekry@platinum:~/myapp$ php create-phar.php
我們可以直接訪問Phar打包的應用啄骇,但這需要額外配置web server來將Phar文件發(fā)送給正確PHP解析器。另外一個辦法是創(chuàng)建一個run腳本瘟斜,include 這個Phar文件
在web server的根目錄創(chuàng)建一個叫 run.php 的PHP腳本:
<?php
require "myapp.phar";
這段代碼的作用就是可以讓你免去了去配置web server來直接解析Phar文件缸夹。如果你的應用使用的是一個共享的虛擬主機,沒有權(quán)限來配置web server螺句,那么虽惭,這種方式是一個完美的解決方案。
創(chuàng)建了run.php后蛇尚,我們的web server的根目錄會變成這樣:
為什么composer命令可以不依賴類php命令而直接運行
如果composer.phar是一個包芽唇,那么正常使用composer應該全部是php composer.phar ** 這樣的形式,為什么我們在日常使用中缺可以
comoser install
這樣的形式來使用呢取劫?
想弄明白為什么匆笤,我們先從composer的安裝開始過程開始研究
curl -sS https://getcomposer.org/installer | php
從命令上我們可以看書研侣,這個安裝命令其實就是從網(wǎng)上下載了installer的PHP文件,然后在本地執(zhí)行炮捧。這個執(zhí)行過程就類似于上面的打包phar包庶诡。最終生成了composer.phar 文件。
- linux系統(tǒng)中 全局安裝,其原理就是: linux系統(tǒng)中文件后綴名并不代表可執(zhí)行類型咆课,所以將composer.phar移動到bin目錄后修改文件名就可以
mv composer.phar /usr/local/bin/composer
- windows系統(tǒng)中composer setup.exe 通過bat文件來實現(xiàn)調(diào)用composer.phar bat文件類似于
@echo off
php53\php %D:\phpStudy\tools\composer.phar %*
在這里有個疑問末誓,就是為什么linux的composer.phar文件就可以直接執(zhí)行,難道comopser.phar是一個可執(zhí)行的二進制文件不需要PHP解釋器嗎? 這個問題思考了許久傀蚌,后來從網(wǎng)上偶然看到一些人在解壓縮phar文件基显,所以我嘗試用文本編輯工具打開composer.phar 蘸吓,就找到了答案
原來在在composer.phar的文件頭部善炫,內(nèi)嵌了一段shell代碼。至此了解了composer的運行前的必要知識库继。
如果想了解composer的運行原理箩艺,建議可以通過閱讀composer來了解
composer
后面一篇再開始講講怎么使用composer!
【參考資料】
http://php.net/manual/en/book.phar.php phar 官方文檔
https://en.wikipedia.org/wiki/PHAR_(file_format) phar wiki
http://www.webhek.com/post/packaging-your-php-apps-with-phar.html PHP開發(fā)常識:什么是Phar?