在 Vue 中捕获 Laravel 验证错误
发布日期:作者: Shane D Rosenthal
验证是一种确保从前端表单或请求提交的数据满足您的预期并确保我们在数据库中存储正确数据的方式。当提交表单或请求时,在我们使用该数据运行任何逻辑之前,我们需要确保它满足我们所有的要求。如果数据不满足我们的要求,我们需要告诉用户他们提交的数据有问题,以便他们可以修复它。
项目
目前,我正在开发一个名为 SavvyHouseHunting.com 的 SAAS 应用程序 - 它是一个平台,允许房地产经纪人创建和分享 360 度视频和图像、文档以及与客户的邮件。该应用程序的一个关键区别在于它是一个 Vue SPA,利用 Vue Router,因此我们无法像在 Blade 视图中那样使用 Blade 助手 @errors
。
在网站的一个区域,允许某些类型的用户“邀请”其他人加入他们的团队;在收到邀请后,用户需要提供一些必要的用户数据才能开始使用。
入门
首先,由于我们不希望用户多次接受邀请,在生成邀请邮件时,我们创建了一个 已签名 URL,如下所示
$invitation = Invitation::create([ 'to' => request('email'), 'user_id' => auth()->user()->id, 'type' => request('type') ]); $link = URL::signedRoute('accept-invitation', ['invitation' => $invitation->id]);Mail::to(request('email'))->send(new InvitationMail(auth()->user(), $link));
邮件将发送给被邀请的用户,其中包含已签名的 URL,当用户点击邮件中的链接时,我们会收到该请求并渲染我们的表单。但是,为了确保签名有效,我们可以使用一个简单的 abort_if
方法,该方法接受一个布尔值、一个 HTTP 状态码以及一个可选的消息发送回用户。
更多逻辑
此外,我们需要查找 invitation
并确保它尚未被接受,模型上有一个 accepted
列,我们将在稍后的过程中将其标记为 true。允许的一个额外注意事项是在此被邀请的用户实际上已经在我们的系统中存在的场景中,也许他们也属于其他人的团队。以下是 accept
方法
abort_if(!request()->hasValidSignature(), 403, 'YOU CAN\'T DO THAT');$invitation = Invitation::find(request('invitation'));abort_if($invitation->accepted, 403, 'That invitation has already been accepted'); $from = User::find($invitation->user_id);try { $user = User::where('email', $invitation->to)->firstOrFail(); $this->createAssociations($user, $invitation, $from); $invitation->accepted = true; $invitation->save(); auth()->login($user); return redirect('/dashboard/communication');} catch (ModelNotFoundException $m) { return view('invitation.accept', compact('invitation'));}
您可以看到我们正在遍历多个实例进行验证。如果请求没有有效的签名,则中止;查找邀请并中止如果它已经被接受;获取被邀请人的电子邮件并在数据库中尝试找到他们;如果是,则可以;创建与邀请人之间的新的关联;将邀请标记为 accepted
;将他们登录到应用程序并重定向到仪表板;如果不是,Laravel 将抛出一个 ModelNotFoundException
。我们可以使用 invitation
对象将他们发送到我们的表单。
实例化组件很简单,我们只需要将邀请作为道具传递
<accept-invitation :invitation="{{$invitation}}"></accept-invitation>
在 Vue 中处理 Laravel 错误
Vue 表单有点长,但本质上,我们将邀请传递到 Vue 组件并将邀请对象添加到隐藏字段,并实例化我们对用户的期望
props: { invitation: { type: Object, required: true, }, },data() { return { user: { first_name: '', last_name: '', email: '', phone_number: '', password: '', password_confirmation: '', }, errors: null, }; },
errors
对象是我们将放置从 post 请求捕获的任何错误的地方。我使用 Tailwind 进行所有样式,div 看起来像这样
<div v-if="errors" class="bg-red-500 text-white py-2 px-4 pr-0 rounded font-bold mb-4 shadow-lg"> <div v-for="(v, k) in errors" :key="k"> <p v-for="error in v" :key="error" class="text-sm"> {{ error }} </p> </div></div>
最后,是 post 方法
methods: { submit() { axios .post('accept-invitation', { user: this.user, invitation: this.invitation }) .then(data => { location.href = '/dashboard/communication'; }) .catch(e => { this.errors = e.data.errors; }); }, },
让我们看看处理此请求的控制器方法
Route::post('accept-invitation', 'InvitationController@submit');
Laravel 表单请求验证
对于此方法,由于我们将多个字段传递给控制器,因此让我们利用 Laravel 的表单请求,这里我们使用两种方法:rules()
和 messages()
,如下所示
public function rules() { return [ 'user.first_name' => ['required', 'string', 'max:255', 'min:2'], 'user.last_name' => ['required', 'string', 'max:255'], 'user.phone_number' => ['required', 'max:255'], 'invitation.type' => ['required', 'string', 'max:255'], 'invitation' => ['required'], 'user.password' => ['required', 'min:6', 'confirmed'], ]; } public function messages() { return [ 'user.first_name.required' => 'Your first name is required', 'user.first_name.min' => 'Your first name must be at least 2 characters', 'user.first_name.max' => 'Your first name cannot be more than 255 characters', 'user.first_name.string' => 'Your first name must be letters only', 'user.last_name.required' => 'Your last name is required', 'user.last_name.min' => 'Your last name must be at least 2 characters', 'user.last_name.max' => 'Your last name cannot be more than 255 characters', 'user.last_name.string' => 'Your last name must be letters only', 'user.phone_number.required' => 'Your phone number is required', 'user.phone_number.max' => 'Your phone number cannot be more than 255 characters', 'user.password.required' => 'You must create a password', 'user.password.min' => 'Your password must be at least 6 characters long', 'user.password.confirmed' => 'Your password confirmation does not match', ]; }
让我们测试一下,看看如果我们传递一个不匹配的密码会得到什么
瞧!我们能够轻松地在 Vue 表单中解析 Laravel 验证错误!
专业提示!
我看到很多人没有做的一件事是在他们的控制器中使用验证后的数据,而不是请求数据。一旦数据被验证,您就可以将其设置为一个仅包含作为数组验证数据的变量。
$validated = $request->validated();
通常,我看到开发人员验证请求,然后使用请求数据,并假设由于验证通过,数据是正确的。但是,如果您忘记验证一个字段呢?您的验证将通过,但数据可能不好。这种方法将使您的验证更强大,并提高您的代码信心!
我是一个科技迷、家庭男人、社区领导人、飞行员和音乐家。从 80 年代中期开始,我就一直拆卸东西,看看它们是如何工作的,并试图将它们重新组装起来,有时比以前状态更好。一路上,我遇到了我生命中的爱人,组建了家庭,在领导和指导他人方面找到了目标,最近还成为了一名飞行员。我对飞行、与周围的人分享世界以及尽可能地观看现场金属音乐表演充满热情。
展望未来,我打算拥有自己的飞机,保持仪表等级,继续教导和指导我们的年轻人,发展我的 YouTube 频道和粉丝,并分享我的热情,影响我能影响的任何人。