How Does the Laravel Validate Service Provider Work? A Deep Dive into milwad-dev/laravel-validate

The LaravelValidateServiceProvider registers publishable assets, merges configuration defaults, and bootstraps country-specific phone validators while optionally auto-registering every rule class with Laravel's validator container.

The service provider in milwad-dev/laravel-validate serves as the integration layer that connects the package's validation logic to your Laravel application. Located at src/LaravelValidateServiceProvider.php, this provider handles everything from asset publishing to runtime validator registration. Understanding its internal phases helps you customize country-specific validation rules and leverage the optional container-based auto-discovery feature.

Register Phase: Asset Publishing and Configuration

During the register() method, the provider prepares all publishable resources and loads the package's foundational configuration. This phase runs early in the application lifecycle to ensure translations and config values are available before the boot process begins.

Publishing Language and Config Files

When running in console mode, the provider makes both language files and the configuration file available for publishing via Artisan commands. The publishLangFiles() method (lines 31‑44) dynamically scans the lang/ directory to create individual publish tags for each language locale, while publishConfigFile() (lines 49‑53) exposes the main configuration under the laravel-validate-config tag.

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

Merging Defaults and Loading Translations

The provider immediately loads translation files using loadTranslationsFrom() (line 24), making validation messages accessible via the validation:: namespace. It then merges the default configuration from the package with your application's config repository using mergeConfigFrom() (line 25), ensuring the laravel-validate key contains sensible defaults even if you haven't published the config file.

Boot Phase: Validator Registration

The boot() method handles runtime behavior, registering country-specific validators and optionally scanning the Rules directory for auto-registration. This phase executes after all service providers have been registered, giving it access to the fully initialized application container.

Country-Specific Phone and Landline Validators

The provider reads the phone-country and landline-country mappings from config/laravel-validate.php (lines 47‑92) to register validator classes with their respective callback utilities. For each country code defined in the configuration, it instantiates the corresponding validator class and passes it to either CountryPhoneCallback or CountryLandlineCallback.

  • Phone validation: Iterates over $countries (lines 63‑68) to register classes like IRPhoneValidator or DEPhoneValidator
  • Landline validation: Iterates over $landlineCountries (lines 69‑73) for wired phone validation logic

These callbacks are stored in src/Utils/CountryPhoneCallback.php and src/Utils/CountryLandlineCallback.php, which handle the actual validation invocation via callPhoneValidator($code, $value).

Optional Container-Based Rule Registration

If you enable 'using_container' => true in the configuration, the provider performs an additional step: it scans every PHP file in src/Rules, constructs the fully-qualified class name, and registers it with Laravel's validator using Validator::extend() (lines 75‑89). This eliminates the need to manually register custom rules like ValidPhone or ValidUuid before using them in validation logic.

How Country Validators Work Internally

While the service provider handles registration, the actual validation execution is delegated to utility classes. When you call a country-specific validation rule, the provider has already populated CountryPhoneCallback with the appropriate validator instances mapped to country codes. The utility's callPhoneValidator() method then invokes the correct class based on the country code passed at runtime.

For example, validating an Iranian phone number uses the mapping defined in config/laravel-validate.php to retrieve the IRPhoneValidator class that was registered during the boot phase.

Practical Configuration and Usage Example

To use the provider's features in your application, ensure the package is discovered via Laravel's auto-discovery (listed in extra.laravel.providers in composer.json), or manually register it in config/app.php:

'providers' => [
    Milwad\LaravelValidate\LaravelValidateServiceProvider::class,
],

With using_container enabled, rules are available immediately. Otherwise, manually extend the validator using the callbacks registered by the provider:

use Illuminate\Support\Facades\Validator;
use Milwad\LaravelValidate\Utils\CountryPhoneCallback;

Validator::extend('iran_phone', function ($attribute, $value, $parameters, $validator) {
    return CountryPhoneCallback::callPhoneValidator('IR', $value);
});

// Usage in request validation
$request->validate([
    'mobile' => 'required|iran_phone',
]);

Summary

  • The LaravelValidateServiceProvider operates in two distinct phases: register() for asset publishing and configuration loading, and boot() for validator registration.
  • During registration, it publishes language files via dynamic tags and merges default config values from config/laravel-validate.php.
  • The boot process registers country-specific validators by mapping country codes to classes in CountryPhoneCallback and CountryLandlineCallback.
  • Enabling using_container in the config triggers automatic discovery and registration of all rule classes in src/Rules.
  • All validation logic is ultimately executed through utility callbacks populated by the provider during initialization.

Frequently Asked Questions

How do I publish only the configuration file without language files?

Run php artisan vendor:publish --tag=laravel-validate-config to publish only the main configuration file to config/laravel-validate.php. Language files use separate tags (validate-lang-{locale}) and can be published individually or all at once.

What happens if I set using_container to false?

When 'using_container' is disabled in the configuration, the provider skips the automatic rule scanning logic (lines 75‑89). You must manually register any custom validation rules from src/Rules using Validator::extend() or use the country-specific callbacks directly via CountryPhoneCallback.

Where are the country validator mappings defined?

The mappings between country codes and validator classes are defined in config/laravel-validate.php (lines 47‑92). The phone-country array maps codes like 'IR' to Milwad\LaravelValidate\Utils\PhoneValidator\IRPhoneValidator::class, while landline-country handles wired phone validation.

Can I add custom country validators without modifying the package source?

Yes. After publishing the configuration file, add your custom country code and fully-qualified validator class name to the phone-country or landline-country arrays in config/laravel-validate.php. The provider will automatically register your custom class with the appropriate callback during the boot phase.

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 →