开发 Laravel 包并发布到 packagist(composer)

开发 Laravel 包并发布到 packagist(composer)

一、前言

本篇文章只适合入门的小白,请大佬们手下留情

很多同学在进行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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 1

写得好 ,学习了 :+1:

2年前 评论
NoTurningBack (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!