Custom validator in Laravel 5

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Fixing Your Custom Validator After Migrating from Laravel 4 to 5

Upgrading a major framework version, especially one as foundational as Laravel, often introduces subtle but significant breaking changes. The scenario you’ve described—where custom code stops working after restructuring how it was included—is extremely common when moving between older and newer versions. As a senior developer, I can tell you that this isn't usually a bug in the code itself, but rather a mismatch in how the framework handles configuration loading and service discovery.

Let’s dive into why your custom validator disappeared and how to fix it by aligning your structure with modern Laravel principles.

The Architectural Shift: Why the Breakage Occurred

The fundamental difference between Laravel 4 and Laravel 5 lies in the shift towards a more robust, Service Container-driven architecture. In Laravel 4, including files via require in configuration files (global.php) was a functional way to bootstrap custom logic. However, as frameworks evolve, they move away from simple procedural includes toward explicit class registration, dependency injection, and dedicated service providers for managing application components.

When you moved your validator structure from a simple file inclusion into the app/ directory, you likely broke the mechanism that was responsible for loading and registering that logic with the framework's service container. Simply placing the file there is not enough; Laravel needs an explicit instruction (via a Service Provider) to know that this class exists and should be utilized during the request lifecycle.

The Correct Approach for Custom Validators in Laravel 5+

Instead of relying on manual file inclusion, the recommended way to introduce custom logic or services in modern Laravel applications is by utilizing Service Providers. A Service Provider is the central hub where you bind services, register event listeners, and define how your application components interact with the framework.

For a custom validator, the most robust approach is often to register your validation rules or custom logic within a dedicated service provider, ensuring it gets loaded only when needed by the request cycle. This aligns perfectly with the principles of building scalable applications, much like those promoted by the broader Laravel ecosystem found on sites like https://laravelcompany.com.

Step-by-Step Implementation

Here is the conceptual way to correctly implement your custom validator logic in a Laravel 5+ context:

1. Create the Validator Class:
Keep your validation logic encapsulated in a dedicated class.

// app/Validators/CustomValidator.php
namespace App\Validators;

use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;

class CustomValidator extends ServiceProvider
{
    /**
     * Register the custom validation rules.
     */
    public function register()
    {
        // Bind your custom logic or rules here if necessary, 
        // though often this is done via Request classes now.
    }

    /**
     * Boot the custom validators.
     */
    public function boot()
    {
        // You could register custom rule types or global validation hooks here.
        // For simple rules, you might define them in a separate configuration file 
        // and load them via this provider.
    }
}

2. Register the Service Provider:
You must tell Laravel about this new component by registering it in your main service container, typically within app/Providers/AppServiceProvider.php.

// app/Providers/AppServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Validators\CustomValidator; // Import your custom class

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register()
    {
        // Bind the validator to the container so it can be resolved later.
        $this->app->singleton(CustomValidator::class, function ($app) {
            return new CustomValidator();
        });
    }

    /**
     * Bootstrap any application services.
     */
    public function boot()
    {
        // Logic that runs when the service is booted.
    }
}

3. Register the Provider:
Finally, ensure your newly created Service Provider is registered in config/app.php. If you followed standard Laravel setup, this step is usually already handled automatically. The key takeaway is moving from manual file inclusion to explicit container binding.

Conclusion

The issue you faced is a classic example of architectural drift during framework upgrades. Moving from a procedural method (manual require) to an object-oriented, container-based approach (Service Providers) requires a corresponding change in how your application components are initialized. By embracing the Service Container pattern, you ensure that your custom logic is loaded and accessible only when necessary, leading to cleaner, more maintainable code. Always strive for architectural consistency when migrating major versions; it saves countless debugging hours down the line.