本文參考超哥寫的 基於 Composer 的 PHP 模組化開發 的詳細實踐版。
開發痛點
我相信很多人,對 composer 不瞭解,在開發包的時候會這樣做:
建立專案(jcc/new-package) -> 寫業務邏輯 -> push 到程式碼倉庫 -> 建立除錯專案 -> 安裝包(composer require jcc/new-package -vvv) -> 除錯 -> 修改專案 -> push 更新程式碼 -> 在除錯專案中更新包程式碼 (composer update -vvv) -> ...
由此可見,不斷重複的提交程式碼,更新程式碼,非常的麻煩,而且不能實時除錯。
本文主要解決的問題:
本地開發包時,可本地測試,不需將程式碼提交到第三方程式碼倉庫,再 composer require 安裝到專案中測試:
建立專案(jcc/new-package) -> 寫業務邏輯 -> 建立除錯專案 -> 配置 composer.json -> 除錯 -> 修改專案 -> 直接在除錯專案除錯 -> ...
由此可見,本地開發可減少 git 提交拉取程式碼的時間,降低了提交的每一個版本儘可能出現的低階錯誤。
本地包開發的工作原理:
Composer 將本地開發的包透過軟連線的方式,從新專案( jcc/taxi )軟連線到除錯專案( jcc/test-taxi/vendor/jcc/texi )
主要用到了 repositories 的 path 型別,更新資訊請移步 文件
Composer 包本地開發
首先我們看一下 Composer 安裝包的結構,正常使用的情況下,拿一個安裝好 laravel/laravel)為例子,開啟 vendor 目錄下的 laravel 會看到以下的結構:
vendor/laravel
├── framework
│ └── src
│ └── Illuminate
│ └── ...
└── tinker
└── src
└── Console
同時看一下 Laravel 專案下的 composer.json 檔案的 require 或 require-dev 的依賴包:
{
...,
"require": {
"php": ">=7.0.0",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0"
},
...
}
由此可以知道目錄結構是對應關係的。
建立目錄並初始化
當然在初始化建立目錄的時候,要注意專案名跟目錄結構一致,例如我的新專案叫 jcc/taxi 那麼我建立的目錄結構應該這樣子:
jcc
└── taxi
接著我們需要在 taxi 下進來進一步的開發,當然,在開發前需要先初始化 composer 配置,在 taxi 目錄下執行:
composer init
按照指示填寫資訊即可:
在 texi 目錄下會多出 composer.json 檔案:
{
"name": "jcc/taxi",
"description": "This is a test.",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "jcc",
"email": "changejian@gmail.com"
}
],
"minimum-stability": "dev",
"require": {}
}
建立開發目錄並設定必要資訊
一般情況下,我們會建立 2 個目錄,一個是 src 用於存放包所有的邏輯程式碼,一個是 tests 用於存放測試用例:
jcc/taxi
├── src
├── tests
├── README.md
├── composer.json
└── LICENSE
要注意的是,我們需要再 composer.json 設定一下 composer 自動載入配置,在 composer.json 加入:
{
...,
"autoload": {
"psr-4": {
"Jcc\\Taxi\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Jcc\\Taxi\\Tests\\": "tests/"
}
},
...
}
更多可以看一下 Composer 自動載入文件
建立測試包專案
首先,在 jcc 目錄下建立一個新的專案,用於測試:
jcc
├── taxi
└── test-taxi
接著初始化 composer 配置,生成 composer.json 檔案:
composer init
然後新增 Repositories 專案,有兩種方式:
第一種:直接執行命令
composer config repositories.jcc path /Users/jiajianchan/Sites/jcc/taxi
第二種:直接在 composer.json 檔案新增:
{
...,
"repositories": {
"jcc": {
"type": "path",
"url": "/Users/jiajianchan/Sites/jcc/taxi"
}
}
}
type 型別為 path,url 為專案的相對路徑.
接下來就是新增依賴,同樣有兩種方式:
Shell:
composer require jcc/taxi:dev-master -vvv
composer.json 中新增:
{
...,
"require": {
"jcc/taxi": "dev-master"
},
...
}
當然要注意版本號,必須在 jcc/taxi 專案中的 composer.json 中設定
minimum-stability
屬性,不然在安裝包的時候會報找不到版本號的錯。
開發以及測試
首先在 jcc/taxi 專案下的 src 中建立 Client.php 檔案:
<?php
namespace Jcc\Taxi;
class Client
{
protected $a;
protected $b;
public function __construct(int $a, int $b)
{
$this->a = $a;
$this->b = $b;
}
public function addTogether()
{
return $this->a + $this->b;
}
}
在 jcc/test-taxi 目錄下安裝一下 jcc/taxi 專案後,新增 test.php 檔案:
// 引入 composer 自動載入檔案
require __DIR__ . '/vendor/autoload.php'
$client = new Jcc\Taxi\Client(5, 1);
echo $client->addTogether() . "\n";
最後,在 jcc/test-taxi 目錄下執行 test.php 檔案,即可得出相加的結果:
php test.php
如果你細心點,會發現,jcc/test-taxi 的 vendor 目錄下的 jcc/taxi
依賴專案是一個 軟連線
。也就是說,你在 jcc/taxi 中的 Client.php
檔案新增一個新方法,然後在 jcc/test-taxi 專案中呼叫即可,不需要重新 composer update 包哦。非常方便。
Laravel 包本地開發
本地開發一個 Laravel 包做法基本與 Composer 包開發一樣,簡單過一下吧。
首先建立一個新的 Laravel 專案:
composer create-project laravel/laravel laravel -vvv
在 Laravel 專案中建立如下目錄:
laravel
├── app
├── ...
└── packages
└── jcc
└── taxi
├── LICENSE
├── README.md
├── composer.json
├── src
│ ├── Taxi.php
│ └── TaxiServiceProvider.php
└── tests
jcc/taxi (vendor/name)
為我們要釋出的 Laravel 包,jcc
對應為github username
,taxi
對應為專案名
。
首先初始化 composer 配置,這個跟正常包開發沒區別,然後在 jcc/taxi 下的 src
目錄建立 TaxiServiceProvider.php
檔案:
<?php
namespace Jcc\Taxi;
use Illuminate\Support\ServiceProvider;
class TaxiServiceProvider extends ServiceProvider
{
public function boot()
{
//
}
public function register()
{
$this->app->singleton('taxi', function () {
return new Taxi;
});
}
}
建立 Taxi.php
檔案:
<?php
namespace Jcc\Taxi;
class Taxi
{
public function printRunning()
{
echo 'running' . "\n";
}
}
最後就是想包註冊到 laravel 專案中,在 config/app.php
新增:
return [
...,
'providers' => [
...,
Jcc\Taxi\TaxiServiceProvider::Class,
],
];
修改 laravel 專案下的 composer.json
檔案:
{
...,
"autoload": {
...,
"psr-4": {
...,
"Jcc\\Taxi\\": "packages/jcc/taxi/src/"
}
},
...
}
並執行命令:
composer dump-autoload
最後在 web.php
中修改一下:
Route::get('/', function () {
app('taxi')->printRunning();
});
此時,我們訪問 laravel 專案的主頁時,會顯示 running
這個單詞,則恭喜你,成功了。
開發一個包說難不難,說易也不易,最重要的是你需要有源源不斷的創造力!
本作品採用《CC 協議》,轉載必須註明作者和本文連結