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

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, 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}$/.

// 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.

Container-Based Auto-Registration

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

// 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:

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:

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

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

$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:

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

Edit resources/lang/en/validate.php to customize the validation message:

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 that verify correct validation behavior. Run the specific test suite:

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 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 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 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, 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. The message() method in 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →