開發 Laravel 包併發布到 packagist(composer)

NoTurningBack發表於2021-10-18

一、前言

本篇文章只適合入門的小白,請大佬們手下留情

很多同學在進行laravel開發時,都會遇到開發重複功能的情況,比如:對於錯誤處理,每個公司有每個公司的標準,所以關於這一塊的處理是不一樣的,網上又沒有特定的包,而自己開發的時候每個專案的錯誤處理又是一樣的?怎麼辦?自己再把寫過的錯誤處理檔案再重新複製一份?這樣是不現實的,為什麼?就舉個很簡單的一個例子,比如你有10個專案,你的10個專案都用到了這個錯誤處理檔案,但是某一天,因為公司的業務調整,需要你修改了某個專案的檔案的錯誤處理,修改好了之後,你再一個專案一個專案的去複製過去,這樣也太繁瑣了。這時候你就需要一個統一的管理工具,那就是利用composer工具開發一個laravel包,只要修改了檔案,直接利用composer更新就好了。

所以我打算寫一個簡單的儲存資訊的demo包,然後通過laravel引入該包並且使用,類似效果如下:

輸入這些資訊提交之後,就會在資料庫增加一條資訊,如下:

二、準備

  • 安裝好composer,會簡單的使用
  • 準備好git,會簡單的使用
  • 準備好mysql資料庫
  • 熟悉laravel6.x文件
  • 準備兩個laravel6.x框架.一個用來開發laravel包,就叫做laravel-6.x-demo;另一個用來使用開發出來的包,就叫做laravel-6.x-formal。以上兩個框架請自己初始化配置,以下不再講

三、開發步驟

1. 利用composer初始化本地包

  • 開啟laravel-6.x-demo專案,在該專案的app的同級目錄建立package,再在package目錄下建立message目錄

  • 在終端進入到剛建立的message目錄,執行composer init,然後終端彈出如下圖的內容:

上面的內容分別是:包名(Package name)->描述(Description )->作者(Author)->穩定性(Minimum Stability [])->包型別(Package Type)->執照(License)->是否引入依賴外部包->是否引入依賴外部開發包->是否確認。

除了包名和作者名可以跟我的不一樣,其他都可以和我的一樣,或者按照自己的(符合composer的規則就行)想法也行

  • 上面的操作做完之後會在message目錄底下多一個composer.json檔案

  • message目錄下建立src目錄,我們開發的原始碼檔案都放在這個目錄,現在結構如下圖所示:

2. 自動載入包

  • 為了你開發的包能夠被框架識別需要在composer.json(注意:不是在package\message\composer.json檔案的)的autoload-dev加入如下語法:

    {
        "autoload-dev": {
            "psr-4": {
                "Tests\\": "tests/",
                "DevPackage\\Message\\":"package/message/src/"
            }
        }
    }

    然後在專案的根目錄下執行composer dump-autoload(注意:這裡的根目錄不是package\message\目錄, 是專案目錄根目錄,下同).

    關於為什麼要進行上述操作請參閱:How to create a PSR-4 autoloader for my project?及composer官方文件自動載入

  • 為了你釋出的包在其他laravel專案能夠自動載入(識別名稱空間),那麼必須在package\message\composer.json,加入如下程式碼

    {
        "autoload": {
            "psr-4": {
                "DevPackage\\Message\\": "src/"
            }
        }
    }

    現在整體的package\message\composer.json檔案就變成了如下內容

    {
        "name": "dp1/message",
        "description": "laravel",
        "type": "library",
        "license": "MIT",
        "authors": [
            {
                "name": "xxx",
                "email": "xxx@163.com"
            }
        ],
        "minimum-stability": "dev",
        "require": {},
        "autoload": {
            "psr-4": {
                "DevPackage\\Message\\": "src/"
            }
        }
    }
    

3. 載入擴充套件包的路由

  • 在終端專案根目錄下使用php artisan make:provider MessageServiceProvider建立服務提供者,然後將MessageServiceProvider.php檔案從app\Providers目錄移動到package\message\src目錄下,注意要修改該檔案名稱空間,內容如下

    <?php
    
    namespace DevPackage\Message;
    
    use Illuminate\Support\ServiceProvider;
    
    class MessageServiceProvider extends ServiceProvider
    {
        /**
         * Register services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    
        /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            //
        }
    }
  • 在配置檔案config\app.phpproviders註冊服務提供者,如下:

    DevPackage\Message\MessageServiceProvider::class
  • 載入擴充套件包的路由

    package\message\src\目錄下建立擴充套件包的路由檔案routes\web.php,web.php內容如下:

    <?php
    
    use Illuminate\Support\Facades\Route;
    
    Route::get('message', function () {
        return "success";
    });
    

    然後在MessageServiceProvider.phpboot()方法下加入如下程式碼,就可以載入路由

        /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // 載入擴充套件包的路由檔案
            $this->loadRoutesFrom(__DIR__.'/routes/web.php');
        }

    然後在終端根目錄下使用php artisan serve啟動服務,在網頁上訪問http://127.0.0.1:8000/message,如果頁面出現success就成功

4. 載入擴充套件包的檢視

  • package\message\src\目錄下建立擴充套件包的檢視檔案views\message.php.html,message.php.html內容如下:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <form action="{{save}}" method="post">
            @csrf
            姓名:<input type="text" name="name" placeholder="請輸入你的名字">
            資訊: <input type="text" name="message" placeholder="請輸入資訊">
            <input type="submit">
        </form>
    </body>
    </html>
    
  • 然後在MessageServiceProvider.phpboot()方法下加入如下程式碼,就可以載入檢視

    /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // 載入擴充套件包的路由檔案
            $this->loadRoutesFrom(__DIR__.'/routes/web.php');
            // 載入擴充套件包的檢視檔案
            $this->loadViewsFrom(__DIR__.'/views', 'message');
        }
  • 修改package\message\src\routes\web.php檔案

    為了web.php檔案不放那麼多程式碼,在擴充套件包建立控制器Http\controllers\MessageController.php,內容如下

    <?php
    
    namespace DevPackage\Message\Http\controllers;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    
    /**
     *
     * @author weirui
     * @date 2021-10-14
     */
    class MessageController extends Controller
    {
        public function index()
        {
            return view("message::message");
        }
    
        public function save(Request $request)
        {
    
        }
    }
    

    那麼web.php就可以修改為

    <?php
    
    use Illuminate\Support\Facades\Route;
    
    /**
     *
     * @author weirui
     * @date 2021-10-14
     */
    Route::group(['namespace' => 'DevPackage\Message\Http\controllers'], function () {
        Route::get('message',"MessageController@index")->name('message');
        Route::post('message', "MessageController@save")->name('save');
    });

在網頁上訪問http://127.0.0.1:8000/message,出現如下頁面就表示成功

5. 載入擴充套件包資料庫遷移

  • 在終端的專案根目錄執行php artisan make:model Message -m,建立message模型和遷移檔案

  • 將模型檔案message.phpapp目錄移動到到擴充套件包的package\message\src\Models目錄下,並且增加內容如下

    <?php
    
    namespace DevPackage\Message\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Message extends Model
    {
        // 黑名單
        protected $guarded = [];
    }
  • 將遷移檔案2021_10_15_094100_create_messages_table.phpdatabase\migrations目錄移動到擴充套件包的package\message\src\database\migrations目錄下,增加內容如下

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    class CreateMessagesTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('messages', function (Blueprint $table) {
                $table->bigIncrements('id');
                $table->string('name');
                $table->string('message');
                $table->string('config');
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('messages');
        }
    }
    
  • .env配置資料庫相關資訊

    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=dev_package
    DB_USERNAME=root
    DB_PASSWORD=root
  • 然後在MessageServiceProvider.phpboot()方法下加入如下程式碼,就可以載入資料庫遷移

    /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // 載入擴充套件包的路由檔案
            $this->loadRoutesFrom(__DIR__.'/routes/web.php');
            // 載入擴充套件包的檢視檔案
            $this->loadViewsFrom(__DIR__.'/views', 'message');
             // 載入擴充套件包的資料庫遷移
            $this->loadMigrationsFrom(__DIR__.'/database/migrations');
        }
  • 執行資料庫遷移命令php artisan migrate,就可以在資料庫看到message這個表

6.載入擴充套件包的配置檔案

  • 修改package\message\src\Http\controllers\MessageController.phpsave()方法

    public function save(Request $request)
    {
        $req = $request->all();
        // 載入擴充套件包的配置檔案
        $config = config('message.config');
        $data = [
            'name' => $req['name'],
            'message' => $req['message'],
            'config' => $config
        ];
        Message::create($data);
    
        return redirect(route('message'));
    }
  • 載入擴充套件包的配置檔案

    在擴充套件包package\message\src\建立config\message.php,內容如下

    <?php
    
    return [
        "config" => 123
    ];
  • 然後在MessageServiceProvider.phpboot()方法下加入如下程式碼,就可以載入配置檔案

    /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // 載入擴充套件包的路由檔案
            $this->loadRoutesFrom(__DIR__.'/routes/web.php');
            // 載入擴充套件包的檢視檔案
            $this->loadViewsFrom(__DIR__.'/views', 'message');
             // 載入擴充套件包的資料庫遷移
            $this->loadMigrationsFrom(__DIR__.'/database/migrations');
            // 載入擴充套件包的配置檔案
            $this->mergeConfigFrom(__DIR__.'/config/message.php', 'message');
        }
  • 增加了配置檔案之後,記得要重新執行php artisan serve重新啟動服務,如果不這樣做,會出現資料庫連線不上的問題

  • 然後在瀏覽器上執行http://127.0.0.1:8000/messagem,向表單輸入內容,如下

​ 提交之後可以看到資料表內容如下

​ 看到欄位config為123就表時成功了

7. 釋出到packagist

  • github 上新建一個倉庫,用來儲存我們開發的包,如下

  • 將我們開發的package\message包上傳到github新建的倉庫中(請自行操作)

  • 將包上傳完了之後開啟packagist網頁,登入,然後點選下圖的Submit

  • Repository URL (Git/Svn/Hg)輸入你剛上傳的包的githubURL,如下圖

  • 點選Check,沒問題之後點選Submit,就可以看到你的包以及釋出成功了。

8. 在專案中引進包

  • 開啟laravel-6.x-formal專案,在根目錄下,使用composer require dp1/message命令(這個命令的來源看下圖)引入你開發的包。

  • 然後在laravel-6.x-formal專案的執行php artisan serve,然後輸入http://127.0.0.1:8000/message(記得要關閉laravel-6.x-demo專案的服務),但是發現頁面上顯示404 not find,這是為什麼呢?經過檢視官方文件,發現是自己在專案laravel-6.x-demopackage\message\composer.json忘記加入發現擴充套件包,那麼,加入如下程式碼

    "extra": {
            "laravel": {
                "providers": [
                    "DevPackage\\Message\\MessageServiceProvider"
                ]
            }
        }

    然後提交到github,而packagist需要等待一小會才會同步更新到

  • 然後在laravel-6.x-formal專案的執行composer remove dp1/message移除包,然後再執行composer require dp1/message引入包,再在終端輸入php artisan serve啟動服務,最後再在瀏覽器輸入http://127.0.0.1:8000/message就可以看到正常的頁面,說明成功了。

  • laravel-6.x-formal專案執行php artisan migrate(請配置好資料庫連線),可以看到下載下來的擴充套件包的資料庫檔案已經建立,在瀏覽器上提交你輸入的資訊,也會儲存到資料庫

    9. 釋出群組檔案

  • 進行群組檔案的釋出是為了你在引用某個包的時候可以自定義這個包裡面的內容,就比如,我想修改在laravel-6.x-formal專案修改我開發的擴充套件包dp1/messae的配置檔案或者很醜的檢視檔案,那麼就要用到釋出群組檔案的功能。

  • 切換回專案laravel-6.x-demo,在package\message\src\MessageServiceProvider.phpboot()方法加入如下程式碼

    /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // 載入擴充套件包的路由檔案
            $this->loadRoutesFrom(__DIR__.'/routes/web.php');
            // 載入擴充套件包的檢視檔案
            $this->loadViewsFrom(__DIR__.'/views', 'message');
            // 載入擴充套件包的資料庫遷移
            $this->loadMigrationsFrom(__DIR__.'/database/migrations');
            // 載入擴充套件包的配置檔案
            $this->mergeConfigFrom(__DIR__.'/config/message.php', 'message');
    
            // 進行包釋出(命令:php artisan vendor:publish,然後選擇你的包)
            $this->publishes([
                // 釋出配置檔案(釋出後的配置檔案會在/config目錄下)
                __DIR__ . '/config/message.php' => config_path('messasge.php'),
                // 帆布檢視檔案(釋出後的檢視檔案會在resource/views/vendor/message下)
                __DIR__ . '/views' => resource_path('views/vendor/message')
            ]);
    
        }
  • 提交程式碼到github,打上版本號(自行操作),可以在packagist看到版本號,如下所示

  • 在專案laravel-6.x-formal中在終端使用命令composer require dp1/message:v1.0.0更新dp1/message包,然後在終端執行命令php artisan vendor/publish,看到你引入的包並選擇,如下

  • 現在可以在專案laravel-6.x-formal看到config\message.php檔案和resources\views\vendor\message\messag.blade.php檔案,你可以在這兩個檔案自定義你要的內容,我在這裡不再演示

四、結尾

第一次寫文章,有寫的不好的,請大家多多見諒,也請大家多多指點。謝謝

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章