Mastering Custom Validation Rules in Laravel

Beyond Built-In Constraints

offers a robust set of built-in validation rules like required, string, and url. These work for 90% of use cases. However, real-world applications often demand more surgical precision. When you need to verify specific domain logic—like ensuring a
YouTube
URL is not just a valid URI format, but actually points to a live video—standard rules fall short. Custom validation rules solve this by encapsulating complex logic into reusable, testable classes.

Prerequisites & Tools

To follow this guide, you should be comfortable with

and the
Laravel
framework. We will utilize the following:

  • Artisan CLI: For generating rule boilerplate.
  • Illuminate\Contracts\Validation\ValidationRule: The interface every custom rule must implement.
  • PHPStorm / Laravel Idea: Recommended for autocompletion and rule discovery.

The Anatomy of a Custom Rule

Generate a new rule using the terminal command: php artisan make:rule YouTubeURLRule. This creates a class in the app/Rules directory. The heart of this class is the validate method.

public function validate(string $attribute, mixed $value, Closure $fail): void
{
    if (!preg_match('/^https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]{11})/', $value, $matches)) {
        $fail('The :attribute is not a valid YouTube URL.');
    }
}

The $attribute is the field name (e.g., youtube_url), $value is the user input, and $fail is the callback you trigger if the validation doesn't pass.

External API Integration

Custom rules aren't limited to string manipulation. You can perform network requests to verify data existence. For instance, to check if a video actually exists, you can call the

oEmbed API within the validate method. If the API returns a 404, simply call the $fail closure. This transforms a simple syntax check into a powerful data integrity tool.

Implementation in Controllers

To use your new rule, instantiate it within your controller's validation array:

$request->validate([
    'video_url' => ['required', new YouTubeURLRule],
]);

Syntax & Best Practices

  • Type Hinting: Always type hint the $value to ensure your logic handles the data correctly.
  • Reusability: Keep rules generic. Instead of hardcoding error messages, use Laravel's translation strings to keep your code clean and localizable.
  • Performance: Be cautious with API calls inside validation rules; consider caching results if the same value is validated frequently.
2 min read