漫談PHP組件、框架、Composer那些事

什麼是組件

組件是一組打包的代碼,是一系列相關的類、接口和Trait,用於幫助咱們解決PHP應用中某個具體問題。例如,你的PHP應用須要收發HTTP請求,可使用現成的組件如guzzle/guzzle實現。咱們使用組件不是爲了從新實現已經實現的功能,而是把更多時間花在實現項目的長遠目標上。php

優秀的PHP組件具有如下特性:html

  • 做用單一:專一於解決一個問題,並且使用簡單的接口封裝功能
  • 小型:小巧玲瓏,只包含解決某個問題所需的最少代碼
  • 合做:PHP組件之間能夠良好合做,組合在一塊兒實現大型項目
  • 測試良好:自己提供測試,並且有充足的測試覆蓋度
  • 文檔完善:應該提供完善的文檔,能讓開發者輕易安裝、理解和使用

組件 vs 框架

咱們選擇框架時,要爲這個框架的工具投入不少,框架一般會提供大量工具,但卻沒有提供咱們所需的某個工具時,痛苦就轉嫁到咱們頭上,咱們要尋找並集成自定義的PHP庫。把第三方代碼集成到框架中是件難事,由於第三方代碼和框架可能沒有使用相同的接口。laravel

選擇框架時,咱們看中的是框架的將來,可是誰又能保證某個框架始終是完成某項工做最好的工具呢?存在多年的大型項目必須有好的表現,並且要時刻作好調整,若是選錯了PHP框架,可能沒法作到這一點。較舊的PHP框架可能因爲缺少社區支持而變慢或過期,這些舊框架一般使用過程式代碼編寫,而沒有使用新式的面向對象代碼以及PHP的一些新特性,總之,決定是否使用PHP框架時,要考慮的事情不少。shell

慶幸的是,Laravel在這些擔心方面表現良好,所以才能在衆多PHP框架中脫穎而出,從某種意義上來講,Laravel也是個基於組件開發的框架(核心組件是自身的Illuminate庫,功能實現上則大量依賴第三方組件),相比Symfony而言,上手又比較簡單,因此兼具了擴展性和易用性。可是,Laravel也存在一些不足,好比Laravel自身的組件不能輕易解耦,用於Laravel框架以外(可是相信這種情況會有好轉,好比其數據庫和隊列組件就能夠解耦出去)。綜合來看,Laravel還是一個出色的框架,能幫組咱們快速建立強大的應用。數據庫

那咱們應該使用組件仍是框架呢?答案是,使用正確的工具作正確的事,若是能經過一些PHP組件快速實現小型項目,那就使用組件,若是有多個團隊成員開發大型項目,並且能從框架提供的約定準則和結構中受益,那就使用框架(若是是在糾結使用什麼框架,那麼選擇Laravel吧,它不會讓你失望),使用框架可以引導並加速項目的開發。json

使用組件

Packagist

咱們在Packagist中查找PHP組件,這個網站用於收集PHP組件,最好的PHP組件在Packagist中都能找到。服務器

好比咱們想使用一個http組件用於收發HTTP消息,在搜索框中搜索http,獲得的第一個結果就是Guzzle,就用它吧。composer

Composer

Packagist是查找PHP組件的社區,Composer則是安裝PHP組件的工具。Composer是PHP的依賴管理器,運行在命令行中,你告訴Composer須要哪些組件,Composer會下載並把這些組件自動加載到你的項目中,就這麼簡單。框架

Composer和Packagist緊密合做,若是你告訴Composer想要使用guzzlehttp/guzzle組件,Composer會從Packagist中獲取guzzlehttp/guzzle組件,找到這個組件的倉庫地址,肯定要使用哪一個版本,還能找出這個組件的依賴,而後把guzzlehttp/guzzle組件及其依賴下載到你的項目中。工具

此外,Composer會爲項目中的全部PHP組件自動生成符合PSR標準的自動加載器,有效地抽象了依賴管理和自動加載,因此,對PHP社區來講,Composer是最重要的附加工具,沒有之一,想一想以前咱們要使用諸如include、require、spl_autoload_register來手動實現自動加載的痛苦日子,這一點也不爲過。

關於Composer的安裝和使用,這裏不贅述,請參考Composer中文網

示例項目

下面咱們經過一個示例項目來演示如何使用Composer和組件來開發一個PHP應用,這個應用的做用是掃描一個CSV文件中的URL,找出死鏈,該應用會向每一個URL發HTTP請求,若是返回的HTTP狀態碼大於等於400,就把這個死鏈發給標準輸出。這是一個命令行應用,開發好以後,咱們會執行這個腳本,傳入csv文件的路徑,在標準輸出中顯示死鏈列表。

安裝組件

開始以前,先看看哪些任務可使用現有的PHP組件解決:咱們須要一個能夠迭代處理csv文件數據的組件,此外還要向csv文件中的每一個URL發送HTTP請求,所以還須要一個能夠發送HTTP請求並檢查HTTP響應的組件。

瀏覽Packagist後,咱們找到guzzlehttp/guzzleleague/csv兩個組件,前者用於處理HTTP消息,後者用於處理CSV數據。下面咱們在項目最頂層運行以下命令:

composer require guzzlehttp/guzzle
composer require league/csv

Composer會將依賴安裝到根目錄的vendor目錄下,安裝完成後,會在根目錄下生成composer.jsoncomposer.lock文件:

composer.lock文件中會列出項目使用的全部PHP組件,以及組件的具體版本號,這實際上是鎖定了項目,讓項目只能使用具體版本的PHP組件。這樣的好處是,composer會下載這個文件中列出的具體版本,而無論Packagist中可用的最新版本是多少,你應該把composer.lock文件歸入版本控制,這樣讓團隊成員使用的PHP版本和你同樣,若是本地開發和服務器使用的PHP組件版本相同,能夠儘可能下降由組件版本不一樣致使的bug。

若是確實要下載最新版本的組件並更新composer.lock,可使用composer update命令。

自動加載

接下來咱們來編寫應用代碼,在根目錄下建立一個scan.php文件,而後在該文件頂部使用require導入Composer建立的自動加載器:

require 'vendor/autoload.php';

Composer建立的自動加載器其實就是個名爲autoload.php的文件,保存在vendor目錄中,Composer下載各個PHP組件時,會檢查每一個組件的composer.json文件,肯定如何加載該組件,獲得這個信息後,Composer會在本地爲該組件建立一個符合PSR標準的自動加載器。這樣咱們就能夠實例化項目中的任何PHP組件,這些組件按需自動加載。

編寫代碼

下面咱們正式使用Guzzle和CSV組件編寫scan.php代碼:

//使用composer自動加載器
require 'vendor/autoload.php';

//實例Guzzle Http客戶端
$client = new GuzzleHttp\Client();

//打開並迭代處理CSV
$csv = League\Csv\Reader::createFromPath($argv[1]);
foreach ($csv as $csvRow) {
    try {
        //發送HTTP GET請求
        $httpResponse = $client->get($csvRow[0]);

        //檢查HTTP響應的狀態碼
        if($httpResponse->getStatusCode() >= 400) {
            throw new Exception();
        }
    } catch (Exception $e) {
            //把死鏈發給標準輸出
            echo $csvRow[0] . PHP_EOL;
    }
}

下面咱們在urls.csv中添加一些URL,一行一個,並且至少有一個是死鏈:

而後打開終端,執行scan.php腳本:

php scan.php urls.csv

咱們傳入了兩個參數,第一個是腳本文件scan.php的路徑,另外一個是CSV文件的路徑。輸出以下:

原文連接:漫談 PHP 組件、框架、Composer 那些事

相關文章
相關標籤/搜索