Laravel扩展包开发
本例我们以我在Github上创建的邀请码项目hinet/laravel-invitecode为例进行说明。
关于源码
本例源码托管在Github,详情查看hinet/laravel-invitecode: invite code for laravel (github.com)
创建项目
你也可以直接在现有项目上进行扩展包开发,创建一个测试项目:
composer create-project laravel/laravel example-app
cd example-app
php artisan serve
扩展包目录
在项目根目录创建packages目录,并在其目录下创建以包名命名的目录
mkdir packages/hinet/laravel-invitecode
结构如下:
|- App
|- packages
|---- laravel-invitecode
|-------- config
|-------- src
|-------- composer.json
初始化
我们使用composer init命令初始化创建包
composer init
执行以上命令并根据提示填写包信息,最终生成的composer.json内容如下:
{
"name": "hinet/laravel-invitecode",
"description": "invite code for laravel",
"keywords": ["invite code", "laravel"],
"type": "library",
"require": {
"illuminate/support": "^9.47"
},
"license": "MIT",
"autoload": {
"psr-4": {
"Hinet\\InviteCode\\": "src/"
}
},
"authors": [
{
"name": "hinet",
"email": "63603636@qq.com"
}
],
"minimum-stability": "dev"
}
注意:我们后面需要创建Facade和Provider,所以illuminate/support包需要引入
添加第三方类库
由于在扩展包中我们需要使用第三方HashId类库来生成邀请码,所以我们需要在composer.json的autoload节点下添加classmap节点来自动加载类库,我们拷贝类库到扩展包的src/Libs目录,并修改composer.json如下:
{
"name": "hinet/laravel-invitecode",
"description": "invite code for laravel",
"keywords": ["invite code", "laravel"],
"type": "library",
"require": {
"illuminate/support": "^9.47"
},
"license": "MIT",
"autoload": {
"classmap": [
"src/Libs/HashGenerator.php",
"src/Libs/Hashids.php"
],
"psr-4": {
"Hinet\\InviteCode\\": "src/"
}
},
"authors": [
{
"name": "hinet",
"email": "63603636@qq.com"
}
],
"minimum-stability": "dev"
}
创建验证码生成类
在src目录创建我们的验证码生成类InviteCode.php,代码如下:
<?php
namespace Hinet\InviteCode;
use Hashids;
use Illuminate\Config\Repository;
/**
* 邀请码生成类
*/
class InviteCode{
protected $config;
private $hashIds;
public function __construct(Repository $config){
$this->config = $config->get('invitecode');
$salt = $this->config['salt'];
if(empty($salt)){
$salt = env('APP_KEY');
}
//实例化HashIds类库
$this->hashIds = new Hashids($salt,$this->config['length'],$this->config['char']);
}
/**
* 生成邀请码
*/
public function enCode($id){
return $this->hashIds->encode($id);
}
/**
* 根据邀请码获取用户ID
*/
public function deCode($code){
$code = $this->hashIds->decode($code);
if(is_array($code)){
return current($code);
}else{
return $code;
}
}
}
创建配置文件
在扩展包根目录创建config目录并创建配置文件config.php,内容如下:
<?php
return [
'length' => 6, //邀请码长度
'char' => '',//生成邀请的字符(不能包括0),默认a-zA-Z1-9
'salt' => '',//加密盐,默认使用APP_KEY
];
创建Provider服务提供者
在项目根目录执行artisan指令创建InviteCodeProvider.
php artisan make:provider InviteCodeProvider
生成的provider会在项目的App/Providers目录,我们将其拷贝到扩展包src/目录,并相应修改命名空间,最终代码如下:
<?php
namespace Hinet\InviteCode;
use Illuminate\Support\ServiceProvider;
class InviteCodeProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//以单例模式注册InviteCode类实例,注意这里注册为InviteCode,后面Facade门面将以InviteCode命名,否则找不到类的实例
$this->app->singleton('InviteCode', function ($app) {
return new InviteCode($app['config']);
});
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//自动发布配置文件,其中invitecode参数为tag
$this->publishes([
__DIR__.'/../config/config.php' => config_path('invitecode.php'),
],'invitecode');
}
}
创建Facade门面
在扩展包创建src/Facades目录,并创建InviteCode.php,代码如下
<?php
namespace Hinet\InviteCode\Facades;
use Illuminate\Support\Facades\Facade;
class InviteCode extends Facade
{
protected static function getFacadeAccessor()
{
//注意这里的Facade名称需与Provider中注册的单例命名一致
return 'InviteCode';
}
}
扩展包发现
在 Laravel 应用的 config/app.php 配置文件中, providers 选项定义了能够被 Laravel 加载的服务提供者列表。 当有人安装你的扩展包时,通常会希望此列表中包含你的服务提供者。你可以在扩展包的 composer.json 文件中的 extra 部分定义服务提供者,而不是让用户手动将你的服务提供者添加到列表中。除了服务提供者,你还可以列出你想要注册的所有 facades :
{
"name": "hinet/laravel-invitecode",
"description": "invite code for laravel",
"keywords": ["invite code", "laravel"],
"type": "library",
"require": {
"illuminate/support": "^9.47"
},
"license": "MIT",
"autoload": {
"classmap": [
"src/Libs/HashGenerator.php",
"src/Libs/Hashids.php"
],
"psr-4": {
"Hinet\\InviteCode\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Hinet\\InviteCode\\InviteCodeProvider"
],
"aliases": {
"InviteCode": "Hinet\\InviteCode\\Facades\\InviteCode"
}
}
},
"authors": [
{
"name": "hinet",
"email": "63603636@qq.com"
}
],
"minimum-stability": "dev"
}
至此,一个Laravel的扩展包已开发完成。
测试
把扩展包添加到项目的 config/app.php
<?php
use Illuminate\Support\Facades\Facade;
return [
'name' => env('APP_NAME', 'Laravel'),
// .....
'providers' => [
\Hinet\InviteCode\InviteCodeProvider::class,
];
// .....
'aliases' => Facade::defaultAliases()->merge([
'InviteCode' => \Hinet\InviteCode\Facades\InviteCode::class,
])->toArray(),
];
修改项目下的 composer.json 文件
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
//....
"hinet/laravel-invitecode": "dev-master"
},
"autoload": {
"psr-4": {
//....
"Hinet\\InviteCode\\": "packages/hinet/laravel-invitecode/src/"
}
},
//....
}
最后执行composer dump-autoload命令加载扩展包,至此可以进行扩展包测试了
发布扩展包
在github创建版本库,将我们创建的扩展包push到版本库中,并在www.packagist.org发布我们的扩展包即可通过composer安装了。
安装扩展包
我们可以通过composer命令安装刚才发布的Laravel扩展包:
composer require hinet/laravel-invitecode
在项目中发布配置:
php artisan vendor:publish --tag=invitecode #此处的tag即为我们在provider中设置的
使用示例
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use InviteCode;
class DemoController extends Controller{
public function index(){
echo InviteCode::enCode(123);
//print NDZ0kA
//echo echo InviteCode::deCode('NDZ0kA');
//print 123
}
}