Laravel扩展包开发

2,010 阅读2分钟

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
    }
}