花了四个月打磨的 Laravel Plus 开源
花了四个月时间,经过了两个项目的打磨,我写的 Laravel Plus 终于像个样子了,可以开箱即用了。
采用最新的 PHP8 的语法,大量借鉴了 SpringBoot 中的 AOP 编程思想,全方面拥抱注解。来看一下吧。
路由和控制器
采用注解路由,避免了在控制器和 api.php
的路由文件间跳转。首先在 api.php
中注册:
use Zenith\LaravelPlus\EasyRouter;
EasyRouter::register();
接着就可以非常流畅的写路由了:
use Zenith\LaravelPlus\Attributes\Routes\GetMapping;
use Zenith\LaravelPlus\Attributes\Routes\PostMapping;
use Zenith\LaravelPlus\Attributes\Routes\Prefix;
#[Prefix(path: '/user')]
class UserController
{
#[GetMapping(path: '/login')]
public function login() {}
#[PostMapping(path: '/register')]
public function register() {}
}
获取请求参数
获取请求参数可以使用 #RequestBody
注解。先注册一个控制器中间件:
use Zenith\LaravelPlus\Middlewares\RequestBodyInjector;
abstract class Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
RequestBodyInjector::class,
];
}
}
然后就可以使用注解来将 Request Body 中的参数注入到类中的,结合 Getter/Setter
就很方便,IDE 给出的提示会很友好:
use Zenith\LaravelPlus\Attributes\Routes\GetMapping;
use Zenith\LaravelPlus\Attributes\Requests\RequestBody;
class UserController extends Controller
{
#[GetMapping(path: '/login')]
public function login(#[RequestBody] RegisterParams $params) {}
}
class RegisterParams
{
// The modifiers must be public or protected.
protected string $username;
protected string $password;
}
参数校验
一样的,你需要先注册中间件,参数校验以及填充默认值:
use Zenith\LaravelPlus\Middlewares\RequestParamsDefaultValueInjector;
abstract class Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
RequestParamsDefaultValueInjector::class
ParameterValidation::class,
];
}
}
接着就可以使用 #[Param]
注解来校验参数了:
use Zenith\LaravelPlus\Attributes\Validators\Param;
class UserController extends Controller
{
#[GetMapping(path: '/login')]
#[Param(key: 'username', rules: 'required|string|max:32', message: 'Username is required.')]
public function login() {}
}
也支持自定义的验证器,如下:
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class PasswordRule implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$isPass = strlen($value) >= 8 && preg_match('/[a-zA-Z]/', $value) &&
preg_match('/\d/', $value) &&
preg_match('/[^a-zA-Z\d]/', $value);
if (! $isPass) {
$fail('The :attribute must be least 8 characters and contain at least one letter, one number and one special character.');
}
}
}
验证规则写类名就可以了:
use Zenith\LaravelPlus\Attributes\Validators\Param;
class UserController
{
#[GetMapping(path: '/login')]
#[Param(key: 'username', rules: PasswordRule::class, message: 'password is error')]
public function login() {}
}
支持参数的默认值设置:
use Zenith\LaravelPlus\Attributes\Validators\Param;
use Zenith\LaravelPlus\Attributes\Requests\RequestBody;
class UserController extends Controller
{
#[Param(key: 'page', rule: 'integer|min:1|max:100', default: 1, required: false, message: 'page is error')]
public function queryList(#[RequestBody] QueryParams $params)
{
dump($params->getPage()); // output: 1
}
}
DTO、VO、Bean
这里的 Bean 和 Java 中的 Bean 并非一个意思,而是 DTO 的意思,就是承载数据的对象。
use Zenith\LaravelPlus\Bean;
/**
* @method getUsername()
* @method setUsername()
* @method getPassword()
* @method setPassword()
*/
class RegisterParams extends Bean
{
protected string $username;
protected string $password;
}
new RegisterParams(['username' => 'bob', 'password' => 'passw0rd'])
除了自动实现 Getter/Setter
外,还支持 toArray()
以及 toJson()
、equal()
等方法, 还可以无限级嵌套。
use Zenith\LaravelPlus\Bean;
class User extends Bean
{
protected Company $company;
}
class Company extends Bean
{
protected string $name;
}
支持数组 Bean 的嵌套:
use Zenith\LaravelPlus\Bean;
use Zenith\LaravelPlus\Attributes\BeanList;
/**
* @method Company[] getCompanies()
*/
class User extends Bean
{
/**
* @var Company[]
*/
#[BeanList(value: Company::class)]
protected array $companies;
}
支持类型转换:
use Zenith\LaravelPlus\Bean::
use Zenith\LaravelPlus\Attributes\TypeConverter;
class User extends Bean
{
#[TypeConverter(value: BoolConverter::class)]
protected BoolEnum $isGuest;
}
class BoolConverter
{
public function convert(bool|string $value): BoolEnum
{
if ($value === 'YES' || $value === 'yes' || $value === 'y' || $value === 'Y') {
return BoolEnum::TRUE;
}
if ($value === 'NO' || $value === 'no' || $value === 'N' || $value === 'n') {
return BoolEnum::FALSE;
}
return $value ? BoolEnum::TRUE : BoolEnum::FALSE;
}
}
依赖注入
Laravel 只支持通过构造函数注入,下面的示例演示了使用注解讲依赖注入到成员属性:
use Zenith\LaravelPlus\Traits\Injectable;
class UserController
{
use Injectable;
#[Autowired]
private UserService $userService;
public function register()
{
$this->userService->register();
}
}
除此之外,还支持 #[Service]
、#[Component]
、#[Logic]
等注入的注解。
总结
总而言之,还有更多其他的功能,比如简化了 CRUD,通过 #[Value]
注入配置到类属性…自动生成接口文档、Mock 数据….
Github 任意门,欢迎点 Star 或者使用、或者参与开发、或者交流讨论。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: