laravel composer 擴展包開發(超詳細)
原文章寫在自己的博客: http://blog.share345.com/2018/02/05/laravel-package-development.html
文章適用於laravel 包開發,當然如果你理解着完成一遍,就可以發現他也適用於 composer 擴展包開發,不是必須在laravel 下。
首先在 laravel 根目錄創建文件夾 packages 這里放置我們准備創建的擴展包,這個目錄只是暫時存放我們的擴展包代碼,等我們開發完成配置好了,就不需要他了。
當然如果你不需要發布你的包,以后也可以就使用這個目錄。packages 目錄和 laravel 的 app 目錄同級
然后進入packages 創建目錄 aex 當然這個名字可以隨意起(最好是作者的名之類的),
接着進入 aex 目錄創建目錄 packagetest 這個目錄的名稱最好是你的擴展包名稱,有點意義。 我就是為了測試,所以就叫做 packagetest 好了
然后創建目錄 src 這里就是我們放置代碼的地方啦。
接着命令行下進入 packages/aex/packagetest 執行 composer init 他會一步步詢問你要填寫的信息:
執行完成你會在 packagetest 目錄下看到 composer.json 內容和上圖一致。 當然其實你也可以直接復制一個 composer.json 不需要 composer init
我的 composer.json 內容如下:
{ "name": "aex/packagetest-for-laravel", "authors": [ { "name": "aex", "email": "email@email.com" } ], "require": {} }
你也可以根據 composer.json 的規則添加相應的其它配置
目前目錄結構是這樣的:
雖然你知道代碼都在 src目錄下,但是 laravel 不知道,所以你要告訴他,即配置 laravel 根目錄的 composer.json
修改 autoload 改為類似如下:
"autoload": { "classmap": [ "database" ], "psr-4": { "App\\": "app/", "Aex\\Packagetest\\": "packages/aex/packagetest/src/" } },
然后創建服務:使用 artisan 命令
php artisan make:provider PackagetestServiceProvider
執行完成,laravel 在 app/Providers下會生成 PackagetestServiceProvider.php 然后你把他剪切到 你的 src目錄:packages/aex/packagetest/src
同時修改代碼的命名空間為你剛剛定義的:namespace Aex\Packagetest; 順便把注冊服務等都寫完吧,完成代碼如下:
1 <?php 2 namespace Aex\Packagetest; 3 use Illuminate\Support\ServiceProvider; 4 class PackagetestServiceProvider extends ServiceProvider 5 { 6 /** 7 * 服務提供者加是否延遲加載. 8 * 9 * @var bool 10 */ 11 protected $defer = true; // 延遲加載服務 12 /** 13 * Bootstrap the application services. 14 * 15 * @return void 16 */ 17 public function boot() 18 { 19 $this->loadViewsFrom(__DIR__ . '/views', 'Packagetest'); // 視圖目錄指定 20 $this->publishes([ 21 __DIR__.'/views' => base_path('resources/views/vendor/packagetest'), // 發布視圖目錄到resources 下 22 __DIR__.'/config/packagetest.php' => config_path('packagetest.php'), // 發布配置文件到 laravel 的config 下 23 ]); 24 } 25 /** 26 * Register the application services. 27 * 28 * @return void 29 */ 30 public function register() 31 { 32 // 單例綁定服務 33 $this->app->singleton('packagetest', function ($app) { 34 return new Packagetest($app['session'], $app['config']); 35 }); 36 } 37 /** 38 * Get the services provided by the provider. 39 * 40 * @return array 41 */ 42 public function provides() 43 { 44 // 因為延遲加載 所以要定義 provides 函數 具體參考laravel 文檔 45 return ['packagetest']; 46 } 47 }
自問自答:
1.為什么創建的服務要放到src 下? – 你要開發擴展包,放到laravel下面就不算擴展包了,你的包以后要給別人用,別人會統一安裝到vendor下的,總不能單獨把 service 文件也打包上傳吧。
同理服務定義了 publish , 配置和視圖不同系統需求肯定不一樣,為了讓人家修改,所以我們提供發布到laravel 原始視圖和配置路徑的方法,總不能讓人家下載了你的到 到 vendor下修改吧。
2.那么 composer.json 里的命名空間為什么修改的是laravel 根目錄的? – 啪!多嘴!哦,不對,啪啪啪啪!!! 問的好!,這個我們還沒講完嘛,后面會給他提出來的,我們需要先跑通我們的代碼,再完善成可發布的
接下來注冊我們的服務到 config/app.php (你使用別人家的包都需要這步的)
添加一行 Aex\Packagetest\PackagetestServiceProvider::class
下一步添加配置文件:
在 src 目錄下添加 config 目錄然后添加文件 packagetest.php 內容如下:
<?php return [ 'options' => [] // 只是為了演示 ];
下一步創建我們的服務真正邏輯實現的代碼: 在src目錄下創建文件 Packagetest.php 內容如下:
1 <?php 2 namespace Aex\Packagetest; 3 use Illuminate\Session\SessionManager; 4 use Illuminate\Config\Repository; 5 class Packagetest 6 { 7 /** 8 * @var SessionManager 9 */ 10 protected $session; 11 /** 12 * @var Repository 13 */ 14 protected $config; 15 /** 16 * Packagetest constructor. 17 * @param SessionManager $session 18 * @param Repository $config 19 */ 20 public function __construct(SessionManager $session, Repository $config) 21 { 22 $this->session = $session; 23 $this->config = $config; 24 } 25 /** 26 * @param string $msg 27 * @return string 28 */ 29 public function test_rtn($msg = ''){ 30 $config_arr = $this->config->get('packagetest.options'); 31 return $msg.' <strong>from your custom develop package!</strong>>'; 32 } 33 }
下一步創建視圖文件:在src目錄下添加views目錄然后添加 packagetest.blade.php
@extends('layouts.app') @section('content') <h1>Packagetest Message</h1> {{$msg}} @endsection
下一步創建門面(Facades): 在src目錄下添加 Facades目錄然后添加 Packagetest.php
1 <?php 2 namespace Aex\Packagetest\Facades; 3 use Illuminate\Support\Facades\Facade; 4 class Packagetest extends Facade 5 { 6 protected static function getFacadeAccessor() 7 { 8 return 'packagetest'; 9 } 10 }
然后命令行執行 :
composer dump-autoload
這樣就能夠使用命名空間 Aex\Packagetest 了,上面在 config/app.php 下添加的服務那行就真正生效了。(如果不執行 dump-autoload 運行程序會報錯,說找不到類)
既然我們定義了門面 那么我們就可以為這個服務添加別名了。在 config/app.php 的 aliases 數組添加一行:
'Packagetest' => Aex\Packagetest\Facades\Packagetest::class
現在我們的目錄結構類似:
至此代碼其實就已經跑通了,但是還沒有完全完成。我們先測試下試試,隨便找個 controller 當然 route要定義好:例如:TestController.php
1 <?php 2 namespace App\Http\Controllers; 3 use Illuminate\Http\Request; 4 use Packagetest; 5 class TestController extends Controller 6 { 7 public function test(Request $request){ 8 $a = Packagetest::test_rtn('Aex'); 9 return view('Packagetest::packagetest',['msg'=>$a]); 10 } 11 }
然后根據路由訪問就可以看到效果啦。為什么說沒有完全完成呢?因為 視圖文件和 config 配置文件還在我們的包里定義,以后發布出去,包會在 vendor目錄下,這些文件不應該在vendor下修改
所以命令行執行:
php artisan vendor:publish --provider="Aex\Packagetest\PackagetestServiceProvider" // --provider 參數指定了要發布的服務 你也可以省略來發布所有
發布后你就會在 laravel 本身的 config目錄 和 views/vendor/packagetest 下看到你的文件了,也就可以按照需求隨意修改了。
最后我們說 修改的laravel 的composer.json ,我們要發布我們的包,讓所有人都能使用 composer 安裝,那么執行如下步驟
去掉 添加的 那行 “Aex\Packagetest\”: “packages/aex/packagetest/src/” 然后 修改 packages/aex/packagetest/composer.json
添加 autoload:
"autoload": { "psr-4": { "Aex\\Packagetest\\": "src/" } }
這樣包就是一個完整獨立的包了,然后把他提交到你的 GitHub 上。
提交到 github 上的我的目錄結構是:
我的地址是:https://github.com/ALawating-Rex/packagetest-for-laravel 有需要參考的可以參考下。
接着就是把包提交到 packagelist了, 網址: https://packagist.org/ 如果沒有賬戶則注冊一個
然后點擊 submit ,填寫項目URL,點擊check
成功后點擊 submit 就完成了。 至此你的包就可以像其它人的一樣通過 composer require 安裝了 
如上圖,兩個箭頭分別代表了包名稱 和 版本
所以安裝這個包的時候你的 composer.json 在require可以加這樣一行:
"aex/packagetest-for-laravel": "dev-master"
安裝之前我們先把我們之前開發的這個包都刪除吧,就假設是一個別人的 laravel 框架要用我們的包: 刪除 packages 文件夾
刪除 config/packagetest.php
刪除 resources/views/vendor/packagetest
conifg/app.php 里面刪除添加的服務和別名
controller 里的改動就保留吧,因為安裝完還是要這么寫一遍 最后執行 composer dump-autoload
下面安裝這個自定義包吧: composer update aex/packagetest-for-laravel
然后添加服務: 修改 config/app.php 添加
Aex\Packagetest\PackagetestServiceProvider::class
和別名的配置:
‘Packagetest’ => Aex\Packagetest\Facades\Packagetest::class
執行 composer dump-autoload
發布資源文件: php artisan vendor:publish –provider=”Aex\Packagetest\PackagetestServiceProvider”
測試通過 大功告成!
額外的:
1.在 packagelist 你的這個包頁面可以看到提示了 Set Up GitHub Service Hook 你可以按照提示辦法安裝,安裝完成后,一旦你的項目有push,這里就會跟着更新。
2.還是 packagelist 頁面,可以看到目前你只有 dev-master 版本,假設你需要其它的版本 你可以去你的 github 項目添加 tag
git tag 1.0.0 && git push –tags
這樣composer require 就可以指定別的版本了。
3.為了別人能夠更加清晰的使用你的包,完善你的 Readme 吧
4.不是必須laravel 框架,單純的 composer 擴展包開發也是按照這個步驟來,只不過需要你摘出 laravel 結合的部分。
