در حال بارگذاری ...

Introducing Rule Class0:00

A smaller but useful new feature in Laravel 5.3 is the new rule class, which basically gives you a fluent API for defining some important validation rules. Let me show you. I have a fresh install of Laravel 5.3 here, but I do want to edit a User so that we can test the validation. So I'm going to run php artisan make:auth, and as you may know, that will whip up some scaffolding for us. I'm going to register for an account. And there we go. We have our account.

Building Account Edit Page0:29

And there we go. We have our account. So next, if I switch back to Sublime, I'm going to go to my routes/web.php file. And maybe the endpoint for that will be something like settings/account, and that will load an AccountsController. And specifically, this will be the form to edit your account, maybe. So we'll hit an edit method. Okay. php artisan make:controller AccountsController. And we'll switch over and add an edit method and load a view.

php artisan make:controller AccountsController. And we'll switch over and add an edit method and load a view. Okay. Next, I'm going to create that view. So accounts/edit.blade.php, and we're going to steal some of the layout here. So if we go to views, and how about the home page? Okay. Let's grab that and paste it in here. Now I can say my account, and let's take a look. Back to Chrome, settings/account, and there we go.

Now I can say my account, and let's take a look. Back to Chrome, settings/account, and there we go. But next, this should only be accessible if you're signed in, right? So within here, I'm going to define this within the constructor, just by saying this->middleware('auth'). Okay. Anyways, we're going to replace this now with a form to view the user's profile. So we're going to have a form that will post to settings/account. We need our CSRF field. method field is superfluous, and we'll say updateAccount.

We need our CSRF field. Method field is superfluous, and we'll say update account. Okay. So why don't we just stick with the name and the email? I have a couple snippets here to save us some time. So the name, and then another one for the email. But next, the value is set to the old, so the old value from the session, and that's useful if you redirect back with some errors. But if we don't have an old value, we do want to default to, in this case, the user's name, and we're using a PHP 7 feature here, which is really useful for stuff like this.

But if we don't have an old value, we do want to default to, in this case, the user's name, and we're using a php 7 feature here, which is really useful for stuff like this. So use the old email, or if that's falsy or null, then we're going to use the email. Okay. Let's pass through the user. Now sometimes for user, I make that globally accessible in all of my views, but we don't have that set up here, so we'll just manually pass it through. And we'll say the user account that we're editing will be auth user. Okay. So if we come back and give this a refresh, there we go.

Okay. So if we come back and give this a refresh, there we go. Looks good. And when we, again, submit this form, and it will submit a POST request, but you know what? Let's bring back method_field, because this is really a PATCH request. So we're going to tell Laravel that we actually want a PATCH. And then I'm going to give it the name, the email, and a button to update the account. Okay. So let's add a route for that.

Adding Update Validation3:15

Okay. So let's add a route for that. When you post to settings/accounts, we're going to hit an update method. And then down here, now we can begin working on the new validation features. Okay. So think about it. The very first thing you'd want to do is validate the request. So we might begin by simply saying that the name is required, and the email is required. But imagine that validation fails. Well, this helper here, the ValidatesRequests trait, it's going to redirect back, but we

But imagine that validation fails. Well, this helper here, the validatesRequest trait, it's going to redirect back, but we don't display the errors anywhere. So I'm going to use a little snippet here. This is something common enough. It makes sense to save it to a snippet. If we have any $errors, then within a alert, we will filter through each one and display it. Good. So let's give it a refresh.

Good. So let's give it a refresh. Let's just use nothing here. Update account. And whoops, it looks like our route is wrong. Let's see. Oh, yeah. I forgot to change that to PATCH. Okay. But if we give it a refresh, there we go.

Okay. But if we give it a refresh, there we go. But yeah, it looks like I need some spacing here, huh? So div class is form-group. That's going to give it some margin bottom. Again, we're just using Twitter Bootstrap here. There we go. Okay. So that part's working. Next, though, I want the email to be, well, not just required, but it should be an email.

Unique Email Pitfalls4:32

So that part's working. Next, though, I want the email to be, well, not just required, but it should be an email address, but it should also be unique. And this is a trap you can fall into a lot. So you might do something like this if you've read the documentation. I want this to be unique on the users table, and specifically the email column in the users table is what I need to be unique. So this is just ensuring that the User can't change their email address to someone else who is signed up for an account, right? So if John changes his email address to Jane's, that should fail, right, because she already

who is signed up for an account, right? So if John changes his email address to Jane's, that should fail, right, because she already has an account, and she's signed up, and we can't have a conflict. And in fact, on our database level, we have a unique constraint out of the box, which means it's not going to work to begin with. For example, let's sign out, and then register, well, we'll do the Jane. Jane Doe. Okay. There we go. So now jane@example.com has an account.

There we go. So now Jane at example.com has an account. So if we sign back into mine, let's try to edit our account. I'm going to change it to Jane at example.com, and what I'm going to do here is remove our unique constraint so that we can see it fail. Update account. Now, in this case, we don't see anything, and that's only because we got through validation, so we didn't do anything else. Why don't we simply say auth user update, and then the name will be the request name. This is actually what's going to throw the error on the database end.

Why don't we simply say auth user update, and then the name will be the request name. This is actually what's going to throw the error on the database end. Okay. So update our user, and then return back. And if we give this another shot, aha, we get a query exception. So we tried to change our email to Jane, but she already has an account, so we can't have two email columns with the same value, so it fails. Now, like I said, in our validation, we could say unique on the users table, and specifically the email column is what we want. Now if we were to come back and change it, it's going to fail for us, which is great.

the email column is what we want. Now if we were to come back and change it, it's going to fail for us, which is great. And this would work perfect for registration. But when we are updating an existing User, well, now we have a new problem. Let's load this, and let's just update the account, but maybe we're changing our name to Jeff. Okay. Update. Now that's going to fail, right? And it fails because of this section right here.

Now that's going to fail, right? And it fails because of this section right here. Now this email already exists in the database, so it fails. So what we have to do in these situations is say, okay, it does need to be unique on the users table, but this person already has an account, so I want you to ignore this particular userID. And we can do that as the third argument, so to speak, here. So I could tack on the authenticated userID. So it gets kind of confusing, right? Should be unique, but what is that?

So if you have a different primary key set, you could override that. And then finally, you could add where conditions on top of it. So you could say it should be unique on the users table, but if the active status is set to one. Yeah, trust me, when you come back to this six months from now, it's not going to make any sense. You'll have to go back to the documentation over and over. But still, let's see if this works. Really quickly, let's make a migration called add_active_to_users_table. Okay, let's go to that.

Really quickly, let's make a migration called addActiveToUsers table. Okay, let's go to that. And we're going to add an integer here. Maybe this specifies if you are an active member or a paying member or something like this. Okay, let's run php artisan migrate. And now if I do php artisan tinker, and we fetch all of our users, active should be set to zero for both. Okay, so now if we come back here, so the email address the User types into the form, well, it has to be unique.

Okay, so now if we come back here, so the email address the User types into the form, well, it has to be unique. And we'll verify it against the users table and specifically the email column. But we can ignore the authenticated User's ID. And the default ID or the default primary key name is fine. But we only want this to apply if the active status is set to zero on what we're comparing against. So let's try it out. Imagine we try to change it to Jane now. It's going to fail, right?

Imagine we try to change it to Jane now. It's going to fail, right? And that's because Jane's active status is set to 0. So we do encounter a duplicate email. We do the where condition, active is 0, so it fails. But now let's imagine that we're going to change it to 1. Okay, well, now that's not going to match up. So it probably should go all the way to the MySQL error, and it does. Notice it doesn't take effect in that case. Again, because Jane's active status is 0, and this check doesn't meet the criteria.

Using Rule Fluent API9:45

Notice it doesn't take effect in that case. Again, because Jane's active status is 0, and this check doesn't meet the criteria. But yeah, either way, very complicated stuff. So instead, we can use Laravel's new Rule class. Let's import that at the top. Use Illuminate\Validation\Rule. Now this kind of feels like a facade, but it's not. If we take a look, it's just a handful of static methods that defer to dedicated classes. Behind the scenes, they're just little wrappers that will ultimately be translated into something just like this.

Behind the scenes, they're just little wrappers that will ultimately be translated into something just like this. It's kind of a nice technique. That way, everything's fully backward compatible, but you have a new fluent API you can use. So for example, if I pull up this unique class, that's one of the rules we can use. Ultimately, it's going to be converted to that string format. Okay, so let's try it. We're going to replace this, and we're going to say email is required. It must be an email. However, we're going to say rule, it should be unique on the users table, but we can ignore

It must be an email. However, we're going to say unique rule, it should be unique on the users table, but we can ignore the authenticated user's id, and I will comment that out. Okay, so we haven't converted all of this over just yet, but to show you the basic shape, this is what you have. Now if you want to dig in, once again, if you call a unique method, that's going to load up a Unique class that I have here. So now if you were to say where, that could be something you can run. You could say ignore. These are all really simple classes that, again, will be converted to the string format.

You could say ignore. These are all really simple classes that, again, will be converted to the string format that we've learned. So let's see if we can do this. Come back to accounts. If I update it, that all works. But if we change it to Jane, it should fail, just like we did before. But trust me, six months from now, this is going to be a lot easier for you. And of course, put all of these on their own line to make it a little easier to consume. But what if we want to add this email constraint?

And now we've completely converted this over to a more readable form. And you can even put these on their own line to make it easier for you. Look in the users table, try to find a matching email. If you do, check to see if its active status is 1. And if so, yeah, we're not going to allow that. And I'll show you. Let's go to User, and let's just grab the last one. Yeah, there's Jane. Okay, Jane is now active. So we should not be able to change to her email address.

Other Rule Options13:00

Now, if you're curious about all of the different options you have, yeah, just go to the Rule class and have a look. So if you want to do in, this would be like the value the user types into the text box should be in this array of items. And that's good for like an enum column or things like that. exists, just make sure that the value you type exists within a table. A common example of that is something like a country. So maybe the country the user selects from a dropdown, it has to be represented in a database. And that way, if they were to edit the form and then change it to something else,

it has to be represented in a database. And that way, if they were to edit the form and then change it to something else, you don't end up in a situation where your database is out of sync. But yeah, it'll take the exact same form. Rule exists on the countries table, specifically in the name column. And then if you want to dig in further, let's see what the Exists class looks like. Here's our API. And in this case, where would be the only one you would care about. But also, final tip, notice that you can pass a closure here, or

And in this case, where would be the only one you would care about. But also, final tip, notice that you can pass a closure here, or just a column and a value. So that means if we were to come back, bring this back to unique, we could replace this with where, and then pass a closure here, where you say query where the active status is set to one. And this is useful, again, if you have multiple things you need to compare against. And yeah, that'll do it for this episode. So in Laravel 5.3, you have a new rule class, which is a simple,

And yeah, that'll do it for this episode. So in Laravel 5.3, you have a new Rule class, which is a simple, fluent interface that ultimately exports something just like this, but in a much more readable fashion.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟