基本套件發佈流程:
套件開發 > push到Github > 在packagist提交
"autoload": {
"classmap": [ "database" ],
"psr-4": {
"App\\": “app/",
"Javck\\Hello\\": "packages/javck/hello/src/"
}
},
composer dump-autoload(銜接上一步)
composer init
生成後的範例如下:
{
"name": "javck/hello",
"description": "This is a test",
"type": "liberary",
"keywords": ["laravel"],
"license": "MIT",
"authors": [
{
"name": "zack lin",
"email": "javck@demo.com"
}
],
"minimum-stability": "stable",
"require": {
"php": ">=7.0.0"
},
"autoload": {
"psr-4": {
"Javck\\Hello\\": "src/"
}
}
}
php artisan make:provider HelloServiceProvider
將生成的app/Providers/HelloServiceProvider.php檔案移至packages/javck/hello/src資料夾內
在config/app.php註冊新建立的provider到providers參數內
'providers' => [
...
Javck\Hello\HelloServiceProvider::class,
...
],
'aliases' => [
...
'Hello' => Javck\Hello\Facades\Hello::class,
],
<?php
namespace Javck\Hello;
use Illuminate\Support\ServiceProvider;
class HelloServiceProvider extends ServiceProvider
{
public function boot()
{
//視圖
$this->loadViewsFrom(__DIR__ . '/views', 'javck');
//路由
$this->loadRoutesFrom(__DIR__. '/routes/web.php');
//遷移
$this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
//執行 php artisan vendor:publish 時會將對應的資料夾和文件複製到對應的位置
$this->publishes([
__DIR__.'/views' => base_path('resources/views/vendor/javck'),
__DIR__.'/config/javck.php' => config_path('hello.php'),
]);
}
public function register()
{
$this->app->singleton('hello', function () {
return new Hello;
});
}
public function provides()
{
return ['hello'];
}
}
return [
'carbon_format' => 'm/d/Y',
'version' => '1.0.0'
];
//packages/javck/hello/src/Hello.php
<?php
namespace Javck\Hello;
class Hello
{
public function __construct()
{
}
public function printRunning()
{
echo 'running' . "\n";
}
public function render()
{
return view('Hello::javck');
}
}
'aliases' => [
...
'Hello' => Javck\Hello\Facades\Hello::class,
],
Step 5.建立套件所需要的視圖檔
路徑為 packages/javck/hello/src/views
Step 6.建立套件的Facade
用於引入套件,方便於容器中取出,建立Facades資料夾,新增擴展至Facade的類別
<?php namespace Javck\Hello\Facades;
use Illuminate\Support\Facades\Facade;
class Hello extends Facade
{
protected static function getFacadeAccessor()
{
return 'hello';
}
}
Step 7.在Package加入路由設定
<?php
Route::group([
'namespace' => 'Javck\Hello\Controllers',
'prefix' => 'hello',
'middleware' => 'web'],
function () {
Route::get('/','DemoController@testHello');
Route::get('render','DemoController@testRender');
Route::get('add','DemoController@testAdd');
}
);
public function boot()
{
...
//Route
include __DIR__ . '/routes/web.php';
...
}
Step 8.在Package加入本地化
//src/lang/en/messages.php
<?php
return [
'greeting' => 'Hello to all of you!'
];
第一參數為本地化的資料夾名稱,第二參數為套件名稱,取用本地化會用到
//src/HelloServiceProvider.php
public function boot()
{
...
//Language
$this->loadTranslationsFrom(__DIR__ . '/lang', 'hello');
$this->publishes([
__DIR__.'/path/to/translations' => resource_path('lang/vendor/hello'),
]);
...
}
PS:publishes方法,用於設定當使用指令 vendor:publish 時,要將package的哪些檔案複製到項目中,路徑Helper函式如下列:
echo __('hello::messages.greeting');
Step 9.在Package加入前端資源
你的Package可能包含 JavaScript、CSS 和圖片
要發布這些前端資源到應用根目錄下的 public 目錄,可以使用服務供應器的 publishes 方法。
在本例中,我們添加一個前端資源組標籤 public,用於發布相關的前端資源組:
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->publishes([
__DIR__.'/path/to/assets' => public_path('vendor/hello'),
], 'public');
}
現在,當使用者執行 vendor:publish 命令時,前端資源將會被複製到指定位置,由於需要在每次包更新時覆蓋前端資源,可以使用 –force 標籤:
php artisan vendor:publish --tag=public --force
Step 10.在發佈文件上打標籤Tag
有時候你可能想要分開發佈套件的前端資源和邏輯資源(設定檔.視圖等),例如你可能想要使用者發布套件設定檔的同時卻不發布前端資源
這可以通過在套件的服務提供器中呼叫 publishes 方法時給它們打上”標籤”來實現。
下面我們在 Package的服務提供器之 boot方法 中來定義兩個發佈組:
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->publishes([
__DIR__.'/../config/hello.php' => config_path('hello.php')
], 'config');
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'migrations');
}
現在,用戶可以在使用以下指令通過引用標籤名來分開發佈這兩個組:
php artisan vendor:publish --tag=config
Step 11.在Package加入中介層
在src建立Middleware資料夾,將建立好的中介層檔案存放到該資料夾內
在套件供應器加入以下程式碼
// boot 方法中添加如下程式碼
public function boot()
{
// ...
$this->addMiddlewareAlias('javck.api', ApiAuthMiddleware::class);
// ...
}
// 添加中介層的别名方法
protected function addMiddlewareAlias($name, $class)
{
$router = $this->app['router'];
if (method_exists($router, 'aliasMiddleware')) {
return $router->aliasMiddleware($name, $class);
}
return $router->middleware($name, $class);
}
Step 12.在套件加入命令Command
在src/加入Commands資料夾,將所有新增的命令檔案放入其中
命令範例如下:
<?php
namespace Javck\Hello\Commands;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\Process;
use Javck\Hello\HelloServiceProvider;
class InstallCommand extends Command
{
/**
* The console 命令名稱.
*
* @var string
*/
protected $name = 'hello:install';
/**
* The console 命令描述.
*
* @var string
*/
protected $description = '安裝 Hello 套件';
protected function getOptions()
{
return [
['force', null, InputOption::VALUE_NONE, '強迫此操作能在正式環境執行', null]
];
}
/**
* Get the composer command for the environment.
*
* @return string
*/
protected function findComposer()
{
if (file_exists(getcwd() . '/composer.phar')) {
return '"' . PHP_BINARY . '" ' . getcwd() . '/composer.phar';
}
return 'composer';
}
public function fire(Filesystem $filesystem)
{
return $this->handle($filesystem);
}
/**
* Execute the console command.
*
* @param \Illuminate\Filesystem\Filesystem $filesystem
*
* @return void
*/
public function handle(Filesystem $filesystem)
{
$this->info('出版套件素材資源,資料庫,設定,視圖以及程式檔案');
$this->call('vendor:publish', ['--force' => true, '--provider' => HelloServiceProvider::class]);
$this->info('為您的資料庫建立相關表單');
$this->call('migrate', ['--force' => $this->option('force')]);
$this->info('Dumping the autoloaded files and reloading all new files');
$composer = $this->findComposer();
$process = new Process([$composer . ' dump-autoload']);
$process->setTimeout(null); // Setting timeout to null to prevent installation from stopping at a certain point in time
$process->setWorkingDirectory(base_path())->run();
$this->info('在資料庫裡頭建立資料中');
$this->call('db:seed');
$this->info('為您的public資料夾加上storage捷徑');
$this->call('storage:link');
$this->info('成功安裝套件,祝您學習愉快!');
}
}
Step 13.在本地端同步進行套件測試
設定要測試項目的composer.json,添加repository項目,方法有兩種:
** 方法1: 在Terminal輸入以下命令,指定repository的路徑
composer config repositories.javck /htdocs/test/packages/javck/hello
** 方法2:直接在composer.json加入以下設定
"repositories": {
"javck": {
"type": "path",
"url": "/htdocs/test/packages/javck/hello"
}
}
添加依賴,方法同樣有兩種:
** 方法1:在Terminal輸入以下命令
composer require javck/easyweb2:dev-master -vvv
** 方法2:直接在composer.json加入以下內容
{
...,
"require”:
{ “javck/hello": "dev-master”
},
...
}
PS:要注意版本號,必須在套件中的 composer.json 中設定 minimum-stability 屬性,不然在安装套件的時候出現會找不到版本號的錯誤。
Step 14.(非必須)建立控制器
如需測試能否使用,可建立一個控制器,撰寫如下:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Hello;
class HomeController extends Controller
{
public function testHello()
{
Hello::render();
}
}
Step 15.設定服務供應器和別名自動發現
這樣就不需要應用載入套件後還需要自己註冊,在 composer.json 加入以下設定
//packages/javck/hello/composer.json
"extra": {
"laravel": {
"providers": [
"Javck\\Hello\\HelloServiceProvider"
],
"aliases": {
"Hello": "Javck\\Hello\\Facades\\Hello"
}
}
},
開啟Terminal,切換到套件目錄,注意關鍵提交需要加入Github Tag,才能夠進行Release
cd packages/javck/hello/
//建立repository
git init
//加入所有的文件
git add .
//將所有改變提交
git commit -m "add package source files."
//加入遠端repository網址
git remote add origin https://github.com/javck/hello_package.git
//將本地版控推到遠端
git push -u origin master
//加入標籤
git tag -a 1.0.0 -m "version 1.0.0"
//上傳標籤
git push --tags
如果使用的是Sourcetree,可進行以下操作
提交到 Packagist, 打开到https://packagist.org
登錄後點擊右上角的 submit,並填入git 的項目地址 https://github.com/javck/hello_package.git
點擊 check 就 OK 了
如套件有新的更新,需要點更新按鈕