# How to Validate VAT IDs with laravel-validate: Complete Implementation Guide

> Easily validate European VAT IDs in Laravel using the milwad-dev/laravel-validate package. This guide provides a complete implementation for securing your applications.

- Repository: [Milwad Khosravi/laravel-validate](https://github.com/milwad-dev/laravel-validate)
- Tags: how-to-guide
- Published: 2026-03-07

---

**The `ValidVatId` rule in `milwad-dev/laravel-validate` validates European VAT numbers using a regex pattern that requires a two-letter country code followed by up to 12 digits, accessible via direct instantiation or container-based string rules.**

The `milwad-dev/laravel-validate` package extends Laravel's validation capabilities with ready-to-use rules for common business requirements. When you need to validate European VAT identification numbers, the package provides the `ValidVatId` rule class that handles format validation automatically. This guide demonstrates how to integrate VAT ID validation into your Laravel applications using both object-oriented and string-based approaches.

## Understanding the ValidVatId Implementation

Located in [`src/Rules/ValidVatId.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidVatId.php), the `ValidVatId` class implements Laravel's `Illuminate\Contracts\Validation\Rule` contract. The `passes()` method normalizes input by stripping non-alphanumeric characters, then validates against the pattern `/[a-zA-Z]{2}[0-9]{0,12}$/`.

```php
// src/Rules/ValidVatId.php
namespace Milwad\LaravelValidate\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValidVatId implements Rule
{
    public function passes($attribute, $value): bool
    {
        $value = preg_replace('/[^a-zA-Z0-9]/', '', $value);
        return preg_match('/[a-zA-Z]{2}[0-9]{0,12}$/', $value);
    }

    public function message(): string
    {
        return __('validate.vat-id');
    }
}

```

The `message()` method returns the translation key `validate.vat-id`, allowing localized error messages through Laravel's localization system.

## Configuration and Registration Methods

The package supports two registration modes controlled by the `using_container` setting in [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php).

### Container-Based Auto-Registration

When `using_container` is set to `true`, the `LaravelValidateServiceProvider` automatically registers all rule classes with Laravel's validator factory:

```php
// src/LaravelValidateServiceProvider.php
if (config('laravel-validate.using_container', false)) {
    $rules = File::files(__DIR__.'/Rules');
    
    foreach ($rules as $rule) {
        $className = 'Milwad\\LaravelValidate\\Rules\\'.$rule->getBasename('.php');
        
        Validator::extend(
            $rule->getFilenameWithoutExtension(),
            fn($attribute, $value, $parameters, $validator) => 
                (new $className($parameters))->passes($attribute, $value)
        );
    }
}

```

This registration allows you to reference rules by their filename in string-based validation definitions.

### Object-Style Usage (Default)

Without enabling container registration, instantiate the rule directly using the fully qualified class name `Milwad\LaravelValidate\Rules\ValidVatId`. This approach requires zero configuration and works immediately after package installation.

## How to Validate VAT IDs with laravel-validate

### Object-Style Validation

Import the rule class and instantiate it in your validation rules array:

```php
use Milwad\LaravelValidate\Rules\ValidVatId;

$rules = [
    'vat_id' => ['required', new ValidVatId()],
];

$validator = validator($request->all(), $rules);

if ($validator->fails()) {
    return redirect()->back()->withErrors($validator);
}

```

This method accepts VAT numbers like `EL123456789` or `DE123456789123`, automatically handling inputs containing spaces or dashes.

### String-Based Validation (Container Mode)

Enable container registration in your configuration file:

```php
// config/laravel-validate.php
'using_container' => true,

```

Reference the rule using the kebab-case filename without the `Valid` prefix:

```php
$rules = [
    'vat_id' => 'required|vat-id',
];

```

Laravel resolves the `vat-id` string to the `ValidVatId` class automatically through the service provider's registration logic.

### Customizing Error Messages

Publish the package language files:

```bash
php artisan vendor:publish --tag=validate-lang-en

```

Edit [`resources/lang/en/validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/en/validate.php) to customize the validation message:

```php
return [
    'vat-id' => 'The :attribute must be a valid European VAT number (e.g. EL123456789).',
];

```

The translation key `validate.vat-id` supports Laravel's standard `:attribute` placeholder for dynamic field name insertion.

## Testing VAT ID Validation

The package includes unit tests in [`tests/Rules/ValidVatIdTest.php`](https://github.com/milwad-dev/laravel-validate/blob/main/tests/Rules/ValidVatIdTest.php) that verify correct validation behavior. Run the specific test suite:

```bash
vendor/bin/phpunit --filter=ValidVatIdTest

```

The test cases confirm that valid formats like `EL123456789` pass validation while malformed IDs (missing country codes or excessive digits) correctly trigger failures.

## Summary

- The `ValidVatId` class in [`src/Rules/ValidVatId.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidVatId.php) validates VAT numbers using the regex pattern `/[a-zA-Z]{2}[0-9]{0,12}$/` after stripping non-alphanumeric characters.
- Enable `using_container` in [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php) to use string-based rule references like `vat-id` instead of object instantiation.
- The rule automatically normalizes inputs by removing spaces, dashes, and special characters before applying format validation.
- Error messages use the translation key `validate.vat-id` and support full localization through Laravel's language files.
- Unit tests in [`tests/Rules/ValidVatIdTest.php`](https://github.com/milwad-dev/laravel-validate/blob/main/tests/Rules/ValidVatIdTest.php) ensure the validation logic correctly handles European VAT number formats.

## Frequently Asked Questions

### What format does the ValidVatId rule expect?

The rule expects a two-letter alphabetic country code followed by up to 12 numeric digits, matching the regex pattern `[A-Z]{2}[0-9]{0,12}`. According to the implementation in [`src/Rules/ValidVatId.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidVatId.php), the `passes()` method automatically strips spaces, dashes, and other non-alphanumeric characters using `preg_replace('/[^a-zA-Z0-9]/', '', $value)` before validation, so formatted inputs like `EL 123 456 789` validate successfully.

### How do I use the VAT validation rule without enabling the container?

You can instantiate the rule directly as an object without any configuration changes. Import `Milwad\LaravelValidate\Rules\ValidVatId` and pass `new ValidVatId()` in your validation rules array. This object-style approach bypasses the container registration system entirely and works immediately after installing the package via Composer.

### Can I customize the validation error message for VAT IDs?

Yes. Publish the language files using `php artisan vendor:publish --tag=validate-lang-en` and modify the `validate.vat-id` key in [`resources/lang/en/validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/en/validate.php). The `message()` method in [`ValidVatId.php`](https://github.com/milwad-dev/laravel-validate/blob/main/ValidVatId.php) returns `__('validate.vat-id')`, allowing you to provide localized messages for different languages using Laravel's standard translation system.

### Does the rule verify VAT IDs against official EU databases?

No. The `ValidVatId` rule only performs format validation using regular expressions to ensure the input matches the structural requirements of European VAT numbers (country code + digits). It does not connect to the VIES (VAT Information Exchange System) database or verify that the number is currently active, assigned to a valid business, or exists in official records.