laravel composer 扩展包开发(超详细)
composer_2">快速发布一个composer扩展包
我之所以想先带大家快速了解一个composer包的发布过程,是因为我打算把二次封装的组件作为composer包发布。我必须了解composer组件怎么发布,有哪些功能。
创建packages
在哪个目录创建packages,我们可以先来看一下vendor。
在上图中,vendor是和app是同一级别的,vendor下存放的是不同的组件。所以我们参照vendor,建立一个packages。我们再来看看包名怎么命名。
- 命名空间(Vendor Name)
通常使用你的公司名、组织名或个人用户名作为命名空间。这有助于区分不同来源的包,并且可以防止命名冲突。命名空间应全部使用小写字母,以保持一致性。 - 包名(Package Name)
包名应该能够清晰地描述包的功能或用途。使用连字符 - 分隔多个单词,而不是下划线 _ 或驼峰命名法。 - 完整的包标识符
vendor-name/package-name
比如
php">laravel/framework
spatie/laravel-permission
tightenco/ziggy
那我们给我们的包起个名字,linxi/exception-helper
,exception-helper其实就是为了更友好的获取异常信息
下面我们进入到这个目录,并初始化一个composer文件
php">$ site/packages/linxi/exception-helper
$ composer init
一路敲enter就行了,不用太纠结。因为这个后面是可以改的。
整个包目录就是长这个样子了。
provider
项目根目录下执行php artisan make:provider ExceptionHelperProvider
,生成一个provider文件,并把文件剪切到packages/linxi/exception-helper/src/
目录下。
那么这个provider有什么作用呢,我们具体来看一下
作用
- 注册服务:
服务提供者是注册应用程序服务的主要位置。使用$this->app->bind()
方法可以将服务绑定到服务容器中,使得该服务可以在整个应用中被解析。 - 引导服务:
除了注册服务外,服务提供者还可以用来引导服务。这可能包括加载配置文件、初始化类实例或设置全局状态。例如,很多服务提供者会在这里注册路由、事件监听器或视图组件。 - 发布配置和资源:
使用publishes方法,服务提供者可以为包或自定义模块发布配置文件、视图、迁移文件等资源,以便开发者可以根据需要进行调整。 - 注册命令:
服务提供者可以通过$commands属性来注册Artisan命令。这些命令可以在命令行界面中使用,用于执行各种任务,如数据库迁移、队列处理等。 - 绑定接口到实现:
在服务提供者中,你通常会定义接口与其实现之间的绑定,这样当接口被解析时,就可以得到正确的实现对象。 - 设置别名:
服务提供者可以设置类的别名(Facade),简化代码书写,使开发更加方便。比如Cache::get(‘key’)这样的写法背后其实是对Illuminate\Cache\CacheManager的一个优雅封装。 - 扩展核心组件:
服务提供者允许你扩展Laravel的核心组件,例如添加自定义的验证规则、日志记录通道等。 - 注册事件监听器、中间件、路由等:
服务提供者可以用来注册事件监听器、中间件以及路由,从而控制请求的生命周期和响应逻辑。 - 延迟加载服务:
如果某个服务不是每次请求都需要,那么可以将其标记为延迟加载(Deferred Provider)。这样,只有当服务真正被请求时才会加载它,有助于提高应用性能。
接下来我们来编辑一下provider类
php"><?phpnamespace Linxi\ExceptionHelper;use Illuminate\Support\ServiceProvider;class ExceptionHelperProvider extends ServiceProvider
{/*** Register services.** @return void*/public function register(){// 绑定异常处理服务到服务容器$this->app->singleton('exception.helper', function ($app) {return new ExceptionHelper();});}public function boot(){// 如果需要引导任何服务,可以在这里进行。// 例如:注册视图组件、事件监听器等。// 视图目录指定$this->loadViewsFrom(__DIR__ . '/views', 'Packagetest');$this->publishes([// 发布视图目录到resources 下
// __DIR__ . '/views' => base_path('resources/views/vendor/packagetest'),// 发布配置文件到 laravel 的config 下__DIR__ . '/config/exception-helper.php' => config_path('exception-helper.php'),]);// 发布视图(如果有)
// $this->loadViewsFrom(__DIR__.'/../resources/views', 'exception-helper');// 注册事件监听器
// \Event::listen(\Illuminate\Auth\Events\Registered::class, \Linxi\ExceptionHelper\Listeners\LogSuccessfulRegistration::class);// 注册中间件(如果需要)$router = $this->app['router'];
// $router->aliasMiddleware('custom.middleware', \Linxi\ExceptionHelper\Http\Middleware\CustomMiddleware::class);// 注册路由(如果需要)
// $this->loadRoutesFrom(__DIR__.'/../routes/web.php');}
}
里面我只用了发布配置文件的功能,对应的包里面的配置文件是src/config目录的exception-helper.php文件,我们先来创建一下文件。
site/packages/linxi/exception-helper/src/config/exception-helper.php
php"><?php
return ['is_dump'=>1,//是否打印异常信息
];
逻辑实现的类
site/packages/linxi/exception-helper/src/ExceptionHelper.php
php"><?phpnamespace Linxi\ExceptionHelper;use Illuminate\Config\Repository;
use Illuminate\Support\Facades\Log;class ExceptionHelper
{protected $config;public function __construct(Repository $config){$this->config = $config;}public function exceptionEcho($msg = '', $data = [], $level = 'INFO'){if (!empty($data) && $data instanceof \Exception) {$data = ['echoLog报错信息' => $data->getMessage(),'echoLog报错文件' => $data->getFile(),'echoLog报错行号' => $data->getLine(),'文件堆栈' => $data->getTraceAsString(),];}$result['msg'] = $msg;if (!empty($data)) {$result['data'] = $data;}//记录日志Log::$level($msg, $result);//如果是error 级别,则飞书报警if ($level == 'error') {//飞书报警// 发飞书消息}if ($this->config->get('exception-helper.is_dump')) {//获取配置参数echo PHP_EOL . json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL;}}}
创建Facade
在包目录下的src下,创建Facades目录,在目录下创建ExceptionHelper.php
php"><?phpnamespace Linxi\ExceptionHelper\Facades;use Illuminate\Support\Facades\Facade;class ExceptionHelper extends Facade
{protected static function getFacadeAccessor(){return 'exception-helper';}
}
php_191">注册到config/app.php
php"> 'providers' => [ \Linxi\ExceptionHelper\ExceptionHelperProvider::class,],'aliases' => ['ExceptionHelper'=>\Linxi\ExceptionHelper\Facades\ExceptionHelper::class,]
那么我们这个包怎么让laravel项目识别呢?我们知道,composer是laravel的包管理工具,所以我们就编辑一下laravel目录下的composer.json文件,在autoload项下增加一个属性,对应的是命名空间和包目录。
php"> "autoload": {"psr-4": {"App\\": "app/","Linxi\\ExceptionHelper\\": "packages/linxi/exception-helper/src/"}}
然后执行composer dump-autoload
重新索引一下包的信息就可以了。
发布引导文件
我们创建provider的时候,指定了一些资源文件和目录,我们使用vendor:publish
把文件发布出来
php">$ php artisan vendor:publish --provider="Linxi\ExceptionHelper\ExceptionHelperProvider"Copied File [/packages/linxi/exception-helper/src/config/exception-helper.php] To [/config/exception-helper.php]
Publishing complete.
看执行结果,我们的配置文件发布到了项目根目录下的config目录下。
测试
接下来我们简单写一点代码测试一下功能
php"> public function handle(){try {throw new \Exception('测试异常');}catch (\Exception $e){ExceptionHelper::exceptionEcho('发短信功能异常',$e,'error');}}
查看打印结果
这样我们的功能就完成了。
包的发布
那么我们怎么把我们的包发布出去呢?我们来看一下
1.发布packages的包到github,我们切换到包的目录下
php">$ cd site/packages/linxi/exception-helper
把包提交到github。并那到github的地址
php">https://github.com/guofuzhang/exception-helper
2.登录https://packagist.org/
关联github的项目地址并发布
发布之后,我们就可以正常通过require来拉取组件了。
接下来我们把我们的项目恢复一下
包的安装
- composer安装
php">composer require linxi/exception-helper
- provider和facade注册到config/app.php
- 发布配置文件
php"> php artisan vendor:publish --provider="Linxi\ExceptionHelper\ExceptionHelperProvider"
- 测试
制品库
我们也可以把我们的包放到制品库里面
配置
在制品库的引导里面设置自己的权限
制作
我们进入package目录下的pusar-client 项目
php">$ zip -r pulsar-client.zip . -x "./vendor/*"
#注意下面的版本号
$ curl -T pulsar-client.zip -u acurd-com@163.com "https://xxxx/pulsar-client?version=v1.0.1"
推送之后就可以在制品库看到推送的版本
拉取
在项目的根目录下创建auth.json,内容就是拉取配置凭证的内容,有这个auth文件才有权限拉取。注意,这个权限表示针对单个项目的,而是针对制品库的。
然后拉取composer包就行了
php">php8 /usr/local/bin/composer require dyxc/pulsar-client:v1.0.1 -vvv
参考
laravel composer 扩展包开发(超详细)