开发 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.php
的providers
注册服务提供者,如下: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.php
的boot()
方法下加入如下代码,就可以加载路由了/** * 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.php
的boot()
方法下加入如下代码,就可以加载视图了/** * 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.php
从app
目录移动到到扩展包的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.php
从database\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.php
的boot()
方法下加入如下代码,就可以加载数据库迁移了/** * 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.php
的save()
方法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.php
的boot()
方法下加入如下代码,就可以加载配置文件了/** * 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
重新启动服务,如果不这样做,会出现数据库连接不上的问题
提交之后可以看到数据表内容如下
看到字段config
为123就表时成功了
7. 发布到packagist
在
github
上新建一个仓库,用来保存我们开发的包,如下将我们开发的
package\message
包上传到github
新建的仓库中(请自行操作)将包上传完了之后打开packagist网页,
登录
,然后点击下图的Submit
在
Repository URL (Git/Svn/Hg)
输入你刚上传的包的github
的URL
,如下图
- 点击
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-demo
的package\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.php
的boot()
方法加入如下代码/** * 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 协议》,转载必须注明作者和本文链接
写得好 ,学习了 :+1: