laravel composer 擴展包開發(超詳細)


laravel composer 擴展包開發(超詳細)

 版權聲明:轉載請注明出處:http://blog.csdn.net/m0sh1 http://blog.share345.com/ https://blog.csdn.net/m0sh1/article/details/79257935

原文章寫在自己的博客: 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 結合的部分。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM