Composer 快速入門

totravel發表於2019-07-05

引言

現代開發,很多的功能不需要自己從零開始實現,因為早就有人實現了這些功能,我們只需要把別人寫好的程式碼拿過來,按照說明來使用就可以了。

相對於自家的程式碼,這些別人家的程式碼就是所謂的 依賴 或者第三方庫。

顯然,手動從別人那兒把程式碼拷貝過來是一件麻煩事兒,特別是依賴非常多的時候。而且,別人家的程式碼有可能進一步依賴更多人的程式碼,這樣,你就不僅要解決自己的依賴,你還要解決依賴的依賴!毫無疑問,這其中的工作量是巨大的,人們迫切需要一個能一鍵解決專案依賴(包括依賴的依賴)的工具,於是,依賴管理工具應運而生。

Composer 是 PHP 的一個依賴管理工具。有了它,你可以很方便地給專案新增和刪除依賴,並且在專案中引用這些依賴也變得非常簡單。

下文將帶你一步一步構建一個使用 Composer 來管理依賴的專案。

新建一個資料夾,充當一個專案的根目錄,然後進入。

$ mkdir demo
$ cd demo

配置檔案

在專案根目錄下建立檔案 composer.json,這個檔案用於說明專案的依賴和其他的一些後設資料。

$ tree
.
└── composer.json

一個很重要的欄位是 require,物件型別,其中列出了專案所需的依賴。

{
    "require": {
        "monolog/monolog": "1.0.*"
    }
}

如你所見,require 下的每一個鍵值對都意味著一個依賴。鍵值對包含了依賴的 包名 和對應的 版本 兩部分資訊:鍵名就是包名,鍵值就是要使用的版本。包名由 作者名稱專案名稱 兩部分構成,中間用一個斜槓 / 隔開。

前面的例子中,將 monolog/monolog 的版本指定為 1.0.*

版本號可以有以下幾種形式:

示例 說明
1.0.2 確切的版本號。
>=1.0
>=1.0, <2.0
<=1.0|>=1.1
比較範圍。逗號 , 解釋為邏輯與;豎線 | 解釋為邏輯或。
1.0.* 相當於 >=1.0.0, <=1.0.9,萬用字元 * 可以是 0-9 中的任一個數字。
1.0 - 2.0 相當於 >=1.0.0, <=2.0.0
~1.2.3 相當於 1.2.3 - 1.2.9,指定一個最小版本,允許最後一個數字增長。
^1.2.3 相當於 1.2.3 - 1.9.9,指定一個版本,允許向下相容的更新。

安裝依賴

執行 Composer 的 install 命令,配置檔案中宣告的依賴就會被安裝,所有的包會被儲存到 vendor 目錄下。

$ composer install

接前面的例子,可以在 vendor/monolog/monolog/ 目錄中看到 monolog/monolog 的原始碼。

$ tree
.
├── composer.json
├── composer.lock
└── vendor
    ├── autoload.php
    ├── composer
    └── monolog
        └── monolog

Composer 為每個作者單獨建立一個目錄,在作者目錄下,又為作者的每個專案單獨建立一個目錄。

首次執行 install 命令,Composer 還會將安裝的依賴的確切版本號寫入檔案 composer.lock。此後再執行 install 命令,Composer 都會優先安裝 composer.lock 檔案中記錄的版本。

日後,如果需要檢查和更新依賴,可以使用 composer update 命令。

使用依賴

如果 Composer 只是下載、儲存和更新包,那 Composer 就談不上有很大作用。

你可能已經注意到,Composer 生成了檔案 vendor/autoload.php,你只需要簡單地 includerequire 這個檔案,就可以直接使用這些包所提供的類。

建立檔案 public/index.php 和日誌檔案 storage/logs/app.log,現在的目錄結構如下:

$ tree
.
├── composer.json
├── composer.lock
├── public
│   └── index.php
├── storage
│   └── logs
│       └── app.log
└── vendor
    ├── autoload.php
    ├── composer
    └── monolog

public/index.php 中包含 vendor/autoload.php,然後直接例項化 monolog/monolog 日誌庫的類,記錄一條日誌。

// public/index.php
require __DIR__ . '/../vendor/autoload.php';

$log = new Monolog\Logger('app');
$log->pushHandler(
    new Monolog\Handler\StreamHandler(
        __DIR__ . '/../storage/logs/app.log',
        Monolog\Logger::WARNING
    )
);

$log->addWarning('Foo');

執行 public/index.php,可以看到日誌已經成功寫到日誌檔案。

$ php public/index.php
$ cat storage/logs/app.log
[2018-10-01 12:04:16] app.WARNING: Foo [] []

工作原理

Composer 是如何做到自動載入第三方類的呢?這要歸功於 PHP FIG 所制定的自動載入規範 PSR-4。Composer 提供的 vendor/autoload.php 檔案已經實現了這些規範,你所要做的就是了解這些規範以及在 Composer 中如何使用。

PSR-4 的核心思想就是將一個頂級名稱空間與某個目錄對應起來,使得該名稱空間下的每一個類都能與一個確切的檔案對應。

例如,對於 App\Http\Kernel 類,如果將頂級名稱空間 App\ 對映為目錄 app/,則檔案 app/Http/Kernel.php 中應該包含 App\Http\Kernel 類。

建立檔案 app/Http/Kernel.php,在這個檔案中定義類 App\Http\Kernel 類。

$ tree
.
├── app
│   └── Http
│       └── Kernel.php
├── composer.json
├── composer.lock
├── public
├── storage
└── vendor
// app/Http/Kernel.php
namespace App\Http;

class Kernel
{
    // 
}

在檔案 composer.json 中的 autoload 欄位中新增欄位 psr-4,在這個欄位中新增一個鍵值對,鍵值為 App\\,鍵值為 app/,這樣就把將頂級名稱空間 App\ 對映為目錄 app/

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
}
  • 名稱空間名稱的最後一級必須帶上反斜槓 \
  • 目錄名後面必須帶上斜槓 /

在檔案 composer.json 中,反斜杆必須寫兩個,因為在 json 中反斜杆具有特殊含義,兩個反斜杆才表示反斜杆本身。

值得注意的是,宣告中的路徑 app/ 是相對於檔案 composer.json 而言的。例如,在 monolog/monolog 日誌庫的 composer.json 檔案中,可以找到如下自動載入器的宣告。

{
  "autoload": {
    "psr-0": {"Monolog": "src/"}
  }
}

這裡的 src/ 對應的是 vendor/monolog/monolog 目錄下的 src 目錄。

改動 autoload 欄位之後,需要執行 dump-autoload 命令,讓 Composer 重新生成 vendor/autoload.php 檔案。

$ composer dump-autoload
Generating autoload files

此後就可以直接使用 App\Http\Kernel 類了。

// public/index.php
require __DIR__ . '/../vendor/autoload.php';

// $log = new Monolog\Logger('app');
// $log->pushHandler(
//     new Monolog\Handler\StreamHandler(
//         __DIR__ . '/../storage/logs/app.log',
//         Monolog\Logger::WARNING
//     )
// );

// $log->addWarning('Foo');

$kernel = new App\Http\Kernel();

autoload 欄位下,除了 psr-4 欄位,還可以有 psr-0classmapfiles 欄位,它們分別對應 PSR-0、類表、檔案清單自動載入方式。

開發時依賴

require 命令用於新增新的依賴。

$ composer require "summerblue/generator:~0.5" --dev

選項 --dev 表示這是一個開發時才會用到的依賴,它將出現在 composer.jsonrequire-dev 欄位中。

{
    "require-dev": {
        "summerblue/generator": "~0.5"
    }
}

--no-dev 選項執行 install 命令,開發依賴就會被跳過。