# Write a custom Laravel validation rule

> A custom rule is a class with validate(). The Vue page still prints form.errors for that field.

- URL: https://laravel-vuejs.space/laravel-custom-validation-rule-vue
- Author: Anass Ez-zouaine (https://laravel-vuejs.space/author/anass-ez-zouaine)
- Published: 2026-10-11
- Topics: Laravel, VueJs, PHP

People searching “Laravel custom validation rule” want one check that `required` and `max` cannot express. The Vue page does not learn a new error shape. It still reads `form.errors.slug` from the [CRUD guide](https://laravel-vuejs.space/laravel-inertia-vue-crud).

> **TL;DR**
>
> -   A custom rule is a class with validate().
> -   The Vue page still prints form.errors for that field.
> -   Do not throw.
> -   Do not reach into the database from this class for a unique check.
>
> **Who it's for:** Laravel + Vue developers
>
> **Applies to:** Laravel 13 · Vue 3

## The fix

```shell
php artisan make:rule SlugRule
```

```php
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class SlugRule implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (! is_string($value) || preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $value) !== 1) {
            $fail('The slug may contain lowercase letters, numbers, and hyphens.');
        }
    }
}
```

```php
$validated = $request->validate([
    'slug' => ['required', 'string', 'max:80', new SlugRule],
]);
```

Call `$fail()` with a sentence. Do not throw. Throwing skips the error bag and the Vue page gets a 500 instead of `form.errors.slug`.

## What to avoid

> **Gotcha**
>
> Do not reach into the database from this class for a unique check. `Rule::unique()` already does that, and a query inside `validate()` is easy to forget when the field is optional.

## FAQ

**Q: How do I write a custom Laravel validation rule?**

A custom rule is a class with validate(). The Vue page still prints form.errors for that field.

**Q: What goes wrong with Laravel custom validation rule?**

Many developers want one check that `required` and `max` cannot express. Do not throw.
