# How to Validate Country-Specific Phone Numbers in Laravel Using Laravel-Validate

> Learn how to validate country-specific phone numbers in Laravel using the milwad-dev laravel-validate package. Map country codes to regex validators for precise validation.

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

---

**Yes, the `milwad-dev/laravel-validate` package validates country-specific phone numbers by mapping ISO-3166-2 country codes to dedicated regex validators via a configurable callback dispatcher.**

The `milwad-dev/laravel-validate` package extends Laravel's validation system with robust support for international phone formats. It ships with 20+ predefined country validators and allows you to validate country-specific phone numbers using either rule objects or string-based validation syntax.

## How Country-Specific Phone Validation Works

The package implements a multi-layered architecture that routes validation logic through a central dispatcher to country-specific regex validators.

### The Entry Point: ValidPhoneNumber Rule

The `ValidPhoneNumber` rule class, located in [`src/Rules/ValidPhoneNumber.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidPhoneNumber.php), serves as the primary interface. It accepts an optional ISO-3166-2 country code via its constructor to trigger country-specific validation.

```php
use Milwad\LaravelValidate\Rules\ValidPhoneNumber;
use Milwad\LaravelValidate\Utils\Country;

// Validates against Iran's phone format
new ValidPhoneNumber(Country::IRAN);

```

When instantiated without arguments, the rule validates generic phone number formats. When passed a country code, it delegates validation to a specialized handler.

### The Dispatcher: CountryPhoneCallback

The `CountryPhoneCallback` class in [`src/Utils/CountryPhoneCallback.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Utils/CountryPhoneCallback.php) manages the mapping between country codes and their validators. The `callPhoneValidator` method routes incoming values to the appropriate validator class based on a static registry populated at boot time.

```php
// From CountryPhoneCallback.php (lines 30-38)
public static function callPhoneValidator(string $countryCode, $value): bool
{
    if (isset(static::$validators[$countryCode])) {
        return (new static::$validators[$countryCode])->validate($value);
    }
    
    throw new \BadMethodCallException("Validator method for '$countryCode' does not exist.");
}

```

### Service Provider Registration

During the `boot()` method of [`src/LaravelValidateServiceProvider.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/LaravelValidateServiceProvider.php), the package reads the `phone-country` configuration array and registers each mapping via `CountryPhoneCallback::addValidator`. This occurs automatically when the service provider loads.

```php
// From LaravelValidateServiceProvider.php (lines 63-67)
$phoneCountries = config('laravel-validate.phone-country', []);
foreach ($phoneCountries as $code => $validator) {
    CountryPhoneCallback::addValidator($code, $validator);
}

```

### Country-Specific Validator Classes

Each supported country implements the `CountryPhoneValidator` interface and contains a tailored regular expression. For example, [`src/Utils/CountryPhoneValidator/SEPhoneValidator.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Utils/CountryPhoneValidator/SEPhoneValidator.php) validates Swedish numbers using this pattern:

```php
public function validate($value): bool
{
    return preg_match('/^(?:\+46|0) ?(?:[1-9]\d{1,2}-?\d{2}(?:\s?\d{2}){2}|7\d{2}-?\d{2}(?:\s?\d{2}){2})$/', $value);
}

```

## Practical Implementation: Validating Phone Numbers by Country

You can implement country-specific validation using several approaches depending on your configuration and requirements.

### Basic Usage with the Rule Class

Instantiate the `ValidPhoneNumber` rule directly in your validation logic, passing the appropriate country constant or string code.

```php
$request->validate([
    // Generic validation (any format)
    'phone' => ['required', new ValidPhoneNumber],
    
    // Iran-specific validation
    'mobile_ir' => ['required', new ValidPhoneNumber(Country::IRAN)],
    
    // Germany-specific using string code
    'phone_de' => ['required', new ValidPhoneNumber('DE')],
]);

```

### String-Based Validation with Container Mode

Enable container-based validation by setting `using_container` to `true` in [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php). This allows you to use Laravel's string-based validation syntax with colon-separated parameters.

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

// In your controller:
$request->validate([
    'phone_ir' => 'required|valid_phone_number:IR',
    'phone_se' => 'required|valid_phone_number:SE',
]);

```

### Adding Custom Country Validators

Extend the package to support countries not included in the default 20+ country set by implementing the `CountryPhoneValidator` interface.

**Step 1:** Create your validator class.

```php
<?php
// src/Utils/CountryPhoneValidator/BRPhoneValidator.php
namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class BRPhoneValidator implements CountryPhoneValidator
{
    public function validate($value): bool
    {
        // Brazil mobile format: +55 XX 9XXXX-XXXX
        return preg_match('/^\+55 ?\d{2} ?9?\d{4}-?\d{4}$/', $value);
    }
}

```

**Step 2:** Register the mapping in [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php).

```php
'phone-country' => [
    'BR' => \Milwad\LaravelValidate\Utils\CountryPhoneValidator\BRPhoneValidator::class,
],

```

**Step 3:** Validate using your custom country code.

```php
$request->validate([
    'phone_br' => ['required', new ValidPhoneNumber('BR')],
]);

```

### Handling Missing Country Validators

If you attempt to validate against a country code that has no registered validator, the `CountryPhoneCallback` throws a `BadMethodCallException` with a descriptive message indicating which validator is missing.

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

try {
    $request->validate([
        'phone' => ['required', new ValidPhoneNumber('AZ')], // Azerbaijan not registered
    ]);
} catch (\BadMethodCallException $e) {
    // Output: "Validator method for 'AZ' does not exist."
}

```

## Summary

- **ValidPhoneNumber** accepts optional ISO-3166-2 country codes (e.g., `IR`, `DE`, `SE`) via its constructor to trigger country-specific validation.
- **CountryPhoneCallback** dispatches validation requests to registered country validators using a static registry populated from the `phone-country` config.
- **LaravelValidateServiceProvider** automatically registers all country validators during the boot phase by iterating over the configuration mappings.
- The package ships with **20+ predefined country validators**, each implementing the `CountryPhoneValidator` interface with tailored regex patterns.
- You can extend validation coverage by creating custom validator classes and registering them in the configuration array.
- Attempting to validate an unregistered country code throws a **BadMethodCallException** rather than failing silently.

## Frequently Asked Questions

### Which countries are supported out-of-the-box?

The package includes validators for over 20 countries including Iran (`IR`), Germany (`DE`), Sweden (`SE`), France (`FR`), and the United Kingdom (`GB`). The complete list is defined in the `phone-country` array within [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php), which maps ISO-3166-2 codes to their respective validator classes in the `src/Utils/CountryPhoneValidator/` directory.

### Can I validate phone numbers using string country codes instead of enums?

Yes. While the package provides a `Country` enum for convenience, the `ValidPhoneNumber` constructor accepts plain strings. You can pass `'IR'`, `'DE'`, or any valid ISO-3166-2 code directly. When using container mode with `using_container` enabled, you must use string codes in the validation rule parameters (e.g., `valid_phone_number:IR`).

### What happens if I use a country code without a registered validator?

The `CountryPhoneCallback::callPhoneValidator` method throws a `BadMethodCallException` with the message "Validator method for '{code}' does not exist." This ensures that validation failures due to missing country support are explicit rather than defaulting to false negatives.

### How do I add support for a country that isn't included by default?

Create a class implementing the `CountryPhoneValidator` interface with a `validate($value): bool` method containing your country's regex pattern. Place this class in your preferred namespace, then add the mapping to the `phone-country` array in [`config/laravel-validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/config/laravel-validate.php) using the ISO-3166-2 code as the key. The service provider will automatically register it on the next request.