Write Your Laravel Validation Logic Like a Senior Dev, Part 2

Making custom rules when they get complicated

Subscribe to my newsletter and never miss my upcoming articles

Listen to 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() and message(). The passes() method will check to see if the $attribute's condition in terms of the $value is met and returns either true or false. The message() method returns whatever string you want to return when passes() 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 for password in our rules() 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:

Screenshot 2021-03-10 152711.jpg

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.

No Comments Yet