在laravel框架中如何有效的验证器验证数据流程步骤
验证是任何现代项目必须具备的,在Laravel中,它是超级简单的开始。
在你的控制器方法中, 你可以调用一个方法, 传入请求, 和一个你想验证的规则数组.
这种方法是正确的吗? 这样做是错的吗?
当然不是,任何告诉你不对的人都需要用湿鱼打一巴掌。这种方法没有错;它是可行的,而且是可测试的。重要的是要记住,虽然它可以被改进,但它可能不需要改进。
下面, 我将带领你了解我在Laravel中的验证之旅, 我做了哪些改变以及为什么。让我们从头开始。
当我开始使用Laravel的时候, 我做的是文档中告诉我的, 简单明了.
我会扩展app/Http/Controller并在这时调用$this->validate。我的控制器很有资源。
我的典型的存储方法看起来有点像下面的,现代的语法:
namespace App\Http\Controllers\Api;
class PostController extends Controller
{
public function store(Request $request): JsonResponse
{
$this->validate($request, [
'title' => 'required|string|min:2|max:255',
'content' => 'required|string',
'category_id' => 'required|exists:categories,id',
]);
$post = Post::query()->create(
attributes: [
...$request->validated(),
'user_id' => auth()->id(),
],
);
return new JsonResponse(
data: new PostResource(
resource: $post,
),
status: Http::CREATED->value,
);
}
}
除了创建逻辑之外,这个验证的工作方式没有任何问题。
我可以对它进行测试和管理,我知道它将按照我的要求进行验证。
所以,如果你的验证是这样的,那就好办了。
然后我转向了可调用的控制器,因为我更喜欢保持事情的简单性
--在这一点上它看起来是一样的,只是用一个调用方法代替了存储方法。
namespace App\Http\Controllers\Api\Posts;
class StoreController extends Controller
{
public function __invoke(Request $request): JsonResponse
{
$this->validate($request, [
'title' => 'required|string|min:2|max:255',
'content' => 'required|string',
'category_id' => 'required|exists:categories,id',
]);
$post = Post::query()->create(
attributes: [
...$request->validated(),
'user_id' => auth()->id(),
],
);
return new JsonResponse(
data: new PostResource(
resource: $post,
),
status: Http::CREATED->value,
);
}
}
在这之后,我发现表单请求是多么有用--以及在这些类中封装我的验证是如何帮助我的。
从那以后,我的控制器又发生了变化。这一次,它看起来像下面这样:
namespace App\Http\Controllers\Api\Posts;
class StoreController
{
public function __invoke(StoreRequest $request): JsonResponse
{
$post = Post::query()->create(
attributes: [
...$request->validated(),
'user_id' => auth()->id(),
],
);
return new JsonResponse(
data: new PostResource(
resource: $post,
),
status: Http::CREATED->value,
);
}
}
我不再需要扩展基础控制器,因为我不需要验证方法。
我可以很容易地将表单请求注入我的控制器的调用方法中,所有的数据都会被预先验证。
这使得我的控制器变得非常小和轻量级,因为我已经把验证推到了一个专门的类。
我的表单请求看起来是这样的:
namespace App\Http\Requests\Api\Posts;
class StoreRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => ['required', 'string', 'min:2', 'max:255',]
'content' => ['required', 'string'],
'category_id' => ['required', 'exists:categories,id'],
];
}
}
有一段时间,我坚持使用这种验证方式,因为同样,它没有什么问题。
如果你的验证看起来像这样,那就好办了。这也是可扩展、可测试和可重复的。
你可以在你使用HTTP请求和需要验证的任何地方注入这个。
不过,我们该何去何从?我们怎样才能改进这个?
这是我问自己的一个问题,并且被卡住了很长时间。让我解释一个场景,它让我对如何处理这个问题产生了疑问。
想象一下,你有一个项目,允许通过一个API、一个网络界面,也许还有命令行来创建帖子。
API和web界面可以共享表单请求,因为两者都可以被注入控制器中。
那么命令行呢?我们需要为此重复验证吗?
有些人可能会说,你不需要对命令行进行同样程度的验证,但你会想要添加一些验证。
我已经玩了一段时间验证器的想法了。
这不是什么新鲜事,所以我也不知道为什么花了这么长时间才想明白 至少对我来说,
验证器是包含验证任何请求--HTTP或其他--所必需的规则和信息的类。
让我告诉你一个可能的样子:
namespace App\Validators\Posts;
class StoreValidator implements ValidatorContract
{
public function rules(): array
{
return [
'title' => ['required', 'string', 'min:2', 'max:255',]
'content' => ['required', 'string'],
'category_id' => ['required', 'exists:categories,id'],
];
}
}
它开始很简单,只是一个我想集中存储这些验证规则的地方。
在那里,我可以根据需要对它进行扩展。
namespace App\Validators\Posts;
class StoreValidator implements ValidatorContract
{
public function rules(): array
{
return [
'title' => ['required', 'string', 'min:2', 'max:255',]
'content' => ['required', 'string'],
'category_id' => ['required', 'exists:categories,id'],
];
}
public function messages(): array
{
return [
'category_id.exists' => 'This category does not exist, you Doughnut',
];
}
}
我可以添加一些东西,比如当我想定制验证信息时的信息。
我可以添加更多的方法来封装更多的验证逻辑。
但这在实践中是怎样的呢?让我们重新审视一下商店控制器的例子。
我们的控制器看起来是一样的,因为我们已经将验证移出,所以让我们看看表单请求:
namespace App\Http\Requests\Api\Posts;
class StoreRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return (new StoreValidator())->rules();
}
}
就这么简单,我可以把卡在一个类里的数组换掉,然后用一个专门针对我们要存储和验证这些信息的类来取代它。
我看到了另一种方法,我觉得有好有坏。让我给你讲讲。
我看到有些人把他们的验证规则放在Eloquent模型中。
现在我对这个方法没有100%的把握,因为我觉得我们会把目的混为一谈--然而,这也是很有创意的。
因为你想做的是把围绕这个模型如何被创建的规则保留在模型本身。
它知道自己的规则。这看起来有点像下面这样:
namespace App\Models;
class Post extends Model
{
public static array $rules = [
'title' => ['required', 'string', 'min:2', 'max:255',]
'content' => ['required', 'string'],
'category_id' => ['required', 'exists:categories,id'],
];
// The rest of your model here.
}
这可以很容易地在表单请求中使用,并与你的模型保持一致,
所以你可以从一个关心这个问题的类中的一个中心点来控制它。
namespace App\Http\Requests\Api\Posts;
class StoreRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return Post::$rules;
}
}
这些是你可以验证数据的几种方法。所有这些都是正确的,而且都可以进行测试。
你喜欢用哪种方式来处理你的验证?
你有什么方法没有在这里或文档中提到吗?
相关文章