Laravel 验证

发布日期 作者

Laravel Validation image

验证是任何现代项目的必备功能,在 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,
);
}
}

除了创建逻辑之外,这种验证方式没有任何问题。我可以测试它并管理它,我知道它会根据我的需要进行验证。所以如果您的验证看起来像这样,做得好!

然后我转移到可调用控制器,因为我更喜欢保持简单 - 在这一点上看起来是一样的,只是使用 invoke 方法而不是 store 方法。

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,
);
}
}

我不再需要扩展基本控制器,因为我不需要 validate 方法。我可以轻松地将表单请求注入到我的控制器 invoke 方法中,所有数据都将预先验证。这使我的控制器变得非常小巧轻便,因为我已经将验证推送到专门的类中。我的表单请求看起来像这样

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、Web 界面,甚至可能是命令行创建帖子。API 和 Web 界面可以共享表单请求,因为两者都可以注入到控制器中。命令行呢?我们需要为它重复验证吗?有些人可能会争辩说,您不需要对命令行进行与 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',
];
}
}

我可以添加诸如消息之类的内容,以便在我想要自定义验证消息时使用。我可以添加更多方法来封装更多验证逻辑。但这在实践中是什么样子的呢?让我们重新审视一下 Store Controller 示例。我们的控制器将看起来和以前一样,因为我们已经移除了验证,所以让我们改来看看表单请求

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 模型中。现在我不确定这一点,因为它感觉我们可能正在混合目的 - 但是,它也很巧妙。因为您想要做的事情是将有关如何创建此模型的规则保留在模型本身中。它知道自己的规则。这看起来有点像下面这样

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

这些是您可以验证数据的几种方法。所有这些都是正确的,并且所有这些都可以测试。您更喜欢哪种方法来处理您的验证?您是否有一种此处或文档中没有提及的方法?请在 Twitter 上告诉我们!

Steve McDougall photo

技术作家,就职于 Laravel 新闻,开发者倡导者,就职于 Treblle。API 专家,资深 PHP/Laravel 工程师。 YouTube 直播主播.

Cube

Laravel 新闻通讯

加入 40,000 多位其他开发者,绝不错过新的技巧、教程等等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

No Compromises

Joel 和 Aaron,来自 No Compromises 播客的两位经验丰富的开发者,现在可以为您雇用 Laravel 项目。 ⬧ 固定费率 7500 美元/月。 ⬧ 没有冗长的销售流程。 ⬧ 没有合同。 ⬧ 100% 退款保证。

No Compromises
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

仅需每月 2500 美元,即可为您的项目配备经验丰富的 Laravel 开发人员,拥有 4-6 年的经验。获得 160 小时的专用专业知识和 15 天的无风险试用。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

Laravel 电子商务。一个开源包,将现代无头电子商务功能的力量带入 Laravel。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。支付、漂亮的结账、管理面板、用户仪表板、身份验证、现成的组件、统计信息、博客、文档等等。

SaaSykit:Laravel SaaS 启动工具包
Rector logo

Rector

您无缝 Laravel 升级、降低成本和加速创新的合作伙伴,帮助公司取得成功

Rector
MongoDB logo

MongoDB

通过将 MongoDB 与 Laravel 强力整合,您可以增强 PHP 应用程序的功能,使开发人员能够轻松高效地构建应用程序。在使用熟悉的 Eloquent API 的同时,支持事务、搜索、分析和移动用例。探索灵活、现代的 MongoDB 数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包为您的 Laravel 应用程序添加评论

阅读文章