Package Data | |
---|---|
Maintainer Username: | tomeet |
Maintainer Contact: | tomeet@sohu.com (tomeet) |
Package Create Date: | 2022-06-21 |
Package Last Update: | 2022-06-28 |
Language: | PHP |
License: | MIT |
Last Refreshed: | 2025-02-01 03:01:24 |
Package Statistics | |
---|---|
Total Downloads: | 8 |
Monthly Downloads: | 0 |
Daily Downloads: | 0 |
Total Stars: | 0 |
Total Watchers: | 1 |
Total Forks: | 0 |
Total Open Issues: | 0 |
A simple and easy-to-use enumeration extension package to help you manage enumerations in your project more conveniently, supporting Laravel and Lumen.
- 一个简单好用的枚举扩展包,帮助你更方便地管理项目中的枚举,支持 Laravel 和 Lumen。
Eloquent\Model
中的 $casts
特性,将查询出的数据自动转换成枚举实例is
、isNot
和in
,用于枚举实例之间的对比CacheEnum
缓存枚举定义,一种统一项目中缓存 key 和缓存过期时间定义的方案;LogEnum
日志枚举定义,用于规范日志记录时的描述内容支持 Laravel 8/Lumen 8 以上版本:
$ composer require Tomeet/laravel-enum -vvv
// config/enum.php
return [
'localization' => [
'key' => env('ENUM_LOCALIZATION_KEY', 'enums'),// 语言包的文件名。如果 APP_LOCALE=zh_CN,则这里对应 resources/lang/zh_CN/enums.php
],
// 通过 transform 中间件将 request 中的参数转换成枚举实例时定义对应关系
// 你可以将请求参数中用到的枚举定义在下面,通过中间件,将会被自动转换成枚举类
'transformations' => [
// 参数名 => 对应的枚举类
],
];
$ php artisan vendor:publish --provider="Tomeet\Enum\Laravel\Providers\LaravelServiceProvider"
// app/Http/Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// ...
protected $routeMiddleware = [
'enum' => \Tomeet\Enum\Laravel\Http\Middleware\TransformEnums::class // 加到这里
];
}
vendor/tomeet/laravel-enum/config/enum.php
,到 config/enum.php
cp vendor/tomeet/laravel-enum/config/enum.php config/enum.php
// bootstrap/app.php
$app->configure('enum');
$app->routeMiddleware([
'enum' => \Tomeet\Enum\Laravel\Http\Middleware\TransformEnums::class,
]);
$app->register(\Tomeet\Enum\Laravel\Providers\LumenServiceProvider::class);
<?php
namespace App\Repositories\Enums;
use Tomeet\Enum\Laravel\Enum;
final class UserTypeEnum extends Enum
{
const ADMINISTRATOR = 0;
const MODERATOR = 1;
const SUBSCRIBER = 2;
const SUPER_ADMINISTRATOR = 3;
}
// 获取常量的值
UserTypeEnum::ADMINISTRATOR;// 0
// 获取所有已定义常量的名称
$keys = UserTypeEnum::getKeys();// ['ADMINISTRATOR', 'MODERATOR', 'SUBSCRIBER', 'SUPER_ADMINISTRATOR']
// 根据常量的值获取常量的名称
UserTypeEnum::getKey(1);// MODERATOR
// 获取所有已定义常量的值
$values = UserTypeEnum::getValues();// [0, 1, 2, 3]
// 根据常量的名称获取常量的值
UserTypeEnum::getValue('MODERATOR');// 1
// 1. 不存在语言包的情况,返回较为友好的英文描述
UserTypeEnum::getDescription(UserTypeEnum::ADMINISTRATOR);// Administrator
// 2. 在 resource/lang/zh_CN/enums.php 中定义常量与描述的对应关系(enums.php 文件名称可以在 config/enum.php 文件中配置)
ExampleEnum::getDescription(ExampleEnum::ADMINISTRATOR);// 管理员
// 补充:也可以先实例化常量对象,然后再根据对象实例来获取常量描述
$responseEnum = new ExampleEnum(ExampleEnum::ADMINISTRATOR);
$responseEnum->description;// 管理员
// 其他方式
ExampleEnum::ADMINISTRATOR()->description;// 管理员
// 检查定义的常量中是否包含某个「常量值」
UserTypeEnum::hasValue(1);// true
UserTypeEnum::hasValue(-1);// false
// 检查定义的常量中是否包含某个「常量名称」
UserTypeEnum::hasKey('MODERATOR');// true
UserTypeEnum::hasKey('ADMIN');// false
// 方式一:new 传入常量的值
$administrator1 = new UserTypeEnum(UserTypeEnum::ADMINISTRATOR);
// 方式二:fromValue
$administrator2 = UserTypeEnum::fromValue(0);
// 方式三:fromKey
$administrator3 = UserTypeEnum::fromKey('ADMINISTRATOR');
// 方式四:magic
$administrator4 = UserTypeEnum::ADMINISTRATOR();
// 方式五:make,尝试根据「常量的值」或「常量的名称」实例化对象常量,实例失败时返回原先传入的值
$administrator5 = UserTypeEnum::make(0); // 此处尝试根据「常量的值」实例化
$administrator6 = UserTypeEnum::make('ADMINISTRATOR'); // 此处尝试根据「常量的名称」实例化
$administrator2 = UserTypeEnum::make('ADMINISTRATOR');// strict 默认为 true;准备被实例化
$administrator3 = UserTypeEnum::make(0);// strict 默认为 true;准备被实例化
// 注意:这里的 0 是字符串类型,而原先定义的是数值类型
$administrator4 = UserTypeEnum::make('0', false); // strict 设置为 false,不校验传入值的类型;会被准确实例化
// 注意:这里的 AdminiStrator 是大小写混乱的
$administrator6 = UserTypeEnum::make('AdminiStrator', false); // strict 设置为 false,不校验传入值的大小写;会被准确实例化
// 随机获取一个常量的值
UserTypeEnum::getRandomValue();
// 随机获取一个常量的名称
UserTypeEnum::getRandomKey();
// 随机获取一个枚举实例
UserTypeEnum::getRandomInstance()
$array = UserTypeEnum::toArray();
/*
[
'ADMINISTRATOR' => 0,
'MODERATOR' => 1,
'SUBSCRIBER' => 2,
'SUPER_ADMINISTRATOR' => 3,
]
*/
$array = UserTypeEnum::toSelectArray();// 支持多语言配置
/*
[
0 => '管理员',
1 => '监督员',
2 => '订阅用户',
3 => '超级管理员',
]
*/
这一部分通过一个需求场景来描述:用户登录 API 需要校验传入的 identity_type 是否合法,并且根据不同的值调用不同的登录逻辑。
<?php
namespace App\Repositories\Enums;
use Tomeet\Enum\Laravel\Contracts\LocalizedEnumContract;
use Tomeet\Enum\Laravel\Enum;
class IdentityTypeEnum extends Enum implements LocalizedEnumContract
{
const NAME = 1;
const EMAIL = 2;
const PHONE = 3;
const GITHUB = 4;
const WECHAT = 5;
}
app/Http/Kernel.php
中添加路由中间件protected $routeMiddleware = [
// ...
'enum' => \Tomeet\Enum\Laravel\Http\Middleware\TransformEnums::class
];
config/enum.php
中配置 Request 参数和枚举之间的转换关系:参数 ⇒ 枚举<?php
use App\Repositories\Enums\IdentityTypeEnum;
return [
'localization' => [
'key' => env('ENUM_LOCALIZATION_KEY', 'enums'),
],
// 你可以将请求参数中用到的枚举定义在下面,通过中间件,将会被自动转换成枚举类
'transformations' => [
// 参数名 => 对应的枚举类
'identity_type' => IdentityTypeEnum::class,
],
];
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Repositories\Enums\IdentityTypeEnum;
use App\Services\AuthorizationService;
use Illuminate\Http\Request;
use Tomeet\Response\Laravel\Support\Facades\Response;
class AuthorizationController extends Controller
{
private AuthorizationService $service;
public function __construct(AuthorizationService $service)
{
$this->middleware('auth:api', ['except' => ['store',]]);
$this->middleware('enum:false');// 请求参数中包含枚举时转换过程中不区分大小写
$this->service = $service;
}
// 假设客户端 POST 方式传入下面参数:(注意,这里 identity_type 传入的值是 email)
/*
{
"identity_type":"email",// 对应 IdentityTypeEnum 中的 EMAIL,这里为小写形式
"account":"longjian.huang@foxmail.com",
"password":"password",
"remember":false
}
*/
public function store(Request $request)
{
$this->validate($request, [
'identity_type' => 'required|enum:'.IdentityTypeEnum::class,// 校验传入的 identity_type 是否能够被实例化成枚举
'account' => 'required|string|max:64|unique:users,account', // 账号
'password' => 'required|min:8', // 密码
'remember' => 'boolean', // 记住我
]);
// identity_type 为 github 时走 Github 登录
// $request->get('identity_type') 为 IdentityTypeEnum 实例,可以调用对象中的方法
if ($request->get('identity_type')->is(IdentityTypeEnum::GITHUB)) {
$token = $this->service->handleGithubLogin($request->all());
}else{
$token = $this->service->handleLogin($request->all());
}
return Response::created($token);
}
}
说明:
\Tomeet\Enum\Laravel\Http\Middleware\TransformEnums
到路由中间件中。$this->middleware('enum:false');
形式使用TransformEnums
中间件,并且向中间件传入了 false 参数。对应上面的UserTypeEnum::make('AdminiStrator', false);
,将不会对枚举参数进行大小写和类型校验$request->get('identity_type')
获取到的是 IdentityTypeEnum
实例,Enum 实例中提供了 is
、isNot
和 in
共 3 种枚举实例之间的比较方法为了实现上面的多账号类型登录,account 数据表中就需要有字段 identity_type
来描述账号类型。
Laravel 的 Eloquent\Model
提供了 $casts
特性,可以将查询出来的数据字段转换成指定类型。这里也可以利用这个特性,将 account 表中的 identity_type
转换成 IdentityTypeEnum
实例。
<?php
namespace App\Repositories\Models\MySql;
use App\Repositories\Enums\IdentityTypeEnum;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $casts = [
'identity_type' => IdentityTypeEnum::class
];
}
为了提高应用性能,在应用中使用缓存是很常见的一种做法。但随着业务到达一定规模后,分散在各处的缓存使用,由于定义缓存 key 的方式不统一,缓存生效时间的不确定性,都会使后期缓存的维护变得困难。
<?php
namespace App\Repositories\Enums;
use Illuminate\Support\Carbon;
use Tomeet\Enum\Laravel\Repositories\Enums\CacheEnum as BaseCacheEnum;
class CacheEnum extends BaseCacheEnum
{
// key => 过期时间计算方法
// 警告:方法名不能相同
const AUTHORIZATION_USER = 'authorizationUser';// 将调用下面定义的 authorizationUser 方法获取缓存过期时间
// ...
// 授权用户信息过期时间定义:将在 Jwt token 过期时一同失效
protected static function authorizationUser($options)
{
$exp = auth('api')->payload()->get('exp'); // token 剩余有效时间
return Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($exp));
}
// ...
}
// app/Providers/EloquentUserProvider.php
public function retrieveById($identifier)
{
// 获取授权用户的缓存 key:类似于 lumen_cache:authorization:user:11
$cacheKey = CacheEnum::getCacheKey(CacheEnum::AUTHORIZATION_USER,$identifier);
// 获取缓存用户缓存的过期时间
$cacheExpireTime = CacheEnum::getCacheExpireTime(CacheEnum::AUTHORIZATION_USER);
return Cache::remember($cacheKey, $cacheExpireTime, function () use ($identifier) {
$model = $this->createModel();
return $this->newModelQuery($model)
->where($model->getAuthIdentifierName(), $identifier)
->first();
});
}
laravel-enum 在下面2 个 package 功能的基础上,扩展增加了松散的(不区分大小写和数据类型) Request 参数转枚举实例,并内置提供了 HttpStatusCodeEnum 和 CacheEnum 等实用枚举集合。
MIT