Write Your Laravel Validation Logic Like a Senior Dev, Part 2
Making custom rules when they get complicated
Play this article
Sometimes the rules that come pre-built into Laravel are not enough. Luckily, Laravel provides a way for you to create your own rules using a separate Rule class. In this post, I'll show you how we can create a custom rule that makes sure passwords are at least 8 characters and includes a symbol, a number, and a lower and upper case letter.
Preliminaries:
- Go back to the previous post to see how you should set up your project.
- This rule will only be used for RegisterRequest, so focus on making sure that's set up properly.
- If you haven't already, download and install Postman.
- Don't forget to run your server!
php artisan serve
The Work Begins:
- We'll create our custom rule by running
php artisan make:rule StrongPassword
.- You can find your new rule in app/Http/Rules/StrongPassword.php.
- In your custom rule you will see a constructor and two methods:
passes()
andmessage()
. Thepasses()
method will check to see if the$attribute
's condition in terms of the$value
is met and returns either true or false. Themessage()
method returns whatever string you want to return whenpasses()
is false.
- The best way to ensure that a string follows a certain pattern is to use regular expressions. In PHP, we use the function
preg_match()
to help with that.
The Work Continues:
- I'm not a god at regex but luckily I found one that works. Here's how we'll pattern match the
$attribute
's$value
to return a boolean:
public function passes($attribute, $value)
{
return preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@()$%^&*=_{}[\]:;\"'|\\<>,.\/~`±§+-]).{8,30}$/", $value);
}
- So if it doesn't pass (returns false), our defined error message will be returned.
public function message()
{
return 'Your :attribute must be at least 8 characters and must include a number, a symbol, a lower and an upper case letter';
}
- NB: Since
password
is the attribute that we're making a rule for, it will replace:attribute
in our string.
The Work Ends:
- Go into RegisterRequest and import
StrongPassword
. Now we need to instantiate it so we can use it. We'll replace the value forpassword
in ourrules()
method and use an array instead.
use App\Rules\StrongPassword;
...
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => ['required', 'string', new StrongPassword],
]
}
- Now when we run it we should see something like this:
Conclusion:
- Having custom rules gives you a lot more options. You can add a lot more logic for even more robust rules. In a future post, I'll show you how I used a trait to make datetime-based custom rules.
- In our next post we'll be discussing After Validation Hooks.