laravel 中合并控制器的多个表单请求为一个的解决方案
laravel 中一个动作(action)方法需要对应编写一个表单请求(FormRequest)类。因此经常懒的去编写表单请求,而是直接在动作中编写验证规则。所以我扩展了表单请求基类,可方便的使一个控制器共用同一个表单请求类。
扩展之后的表单请求基类(app/Http/Requests/FormRequest)
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Illuminate\Contracts\Validation\Validator;
use InvalidArgumentException;
class FormRequest extends \Illuminate\Foundation\Http\FormRequest
{
/**
* 指示验证是否应在第一个规则失败后停止。
*
* @var bool
*/
protected $stopOnFirstFailure = true;
public function validationData()
{
return $this->call(__FUNCTION__, $args = func_get_args(), parent::{__FUNCTION__}(...$args));
}
public function authorize(): bool
{
return $this->call(__FUNCTION__, func_get_args(), true);
}
public function rules(): array
{
return $this->call(__FUNCTION__, func_get_args(), []);
}
public function messages(): array
{
return $this->call(__FUNCTION__, $args = func_get_args(), parent::{__FUNCTION__}(...$args));
}
public function attributes(): array
{
return $this->call(__FUNCTION__, $args = func_get_args(), parent::{__FUNCTION__}(...$args));
}
protected function failedValidation(Validator $validator)
{
return $this->call(__FUNCTION__, $args = func_get_args(), parent::{__FUNCTION__}(...$args));
}
protected function failedAuthorization()
{
return $this->call(__FUNCTION__, $args = func_get_args(), parent::{__FUNCTION__}(...$args));
}
public function validator(ValidationFactory $factory): Validator
{
return $this->call(__FUNCTION__, func_get_args(), $this->createDefaultValidator($factory));
}
protected function withValidator(Validator $validator): Validator
{
return $this->call(__FUNCTION__, func_get_args(), $validator);
}
/**
* @return callable|string
*/
protected function after()
{
return $this->call(
__FUNCTION__,
func_get_args(),
/**
* @return mixed
*
* @throws \Throwable
*/
static function (Validator $validator) {
return $validator;
}
);
}
protected function call(string $method, array $args = [], $defaultReturn = null)
{
$actionMethod = transform($method, function (string $method) {
if (! in_array(
$method,
[
'validationData',
'authorize',
'rules',
'messages',
'attributes',
'failedValidation',
'failedAuthorization',
'validator',
'withValidator',
'after',
],
true
)) {
throw new InvalidArgumentException("Can't call the method[$method].");
}
return $this->route()?->getActionMethod().ucfirst($method);
});
if (method_exists($this, $actionMethod)) {
return $this->$actionMethod(...$args);
}
if (method_exists(parent::class, $method)) {
return parent::$method(...$args);
}
return $defaultReturn;
}
}
使用示例
认证表单请求
<?php
namespace App\Http\Requests\Api;
use App\Http\Requests\FormRequest;
class AuthRequest extends FormRequest
{
public function registerRules()
{
return [
'email' => 'required|email|unique:App\Models\JWTUser,email',
'password' => 'required|string|min:8|confirmed',
'password_confirmation' => 'required|same:password',
];
}
public function loginRules()
{
return [
'email' => 'required|email',
'password' => 'required|string|min:8|confirmed',
];
}
}
认证控制器
<?php
namespace App\Http\Controllers\Api;
use App\Http\Requests\Api\AuthRequest;
class AuthController extends Controller
{
public function register(AuthRequest $request)
{
$validated = $request->validated();
...
}
public function login(AuthRequest $request)
{
$validated = $request->validated();
...
}
}
原文链接
本作品采用《CC 协议》,转载必须注明作者和本文链接
No practice, no gain in one's wit.
我的 Gitub
麻烦的很,首先你可以写个命令自动生成请求、控制器,然后每个控制器还要自己手动验证??$validated = $request->validated();
如果是懒得创建文件得话,推荐使用 Attribute:
Controller:
Validation:
业务控制器:
这个能做到指定场景吗?就比如 register 方法里面使用 login 路由对应的规则
还发现个问题,如果没有路由方法的时候,就会出现死循环的情况。