Julian Julian - 1 month ago 11x
PHP Question

Laravel deferred service provider `provides` not being called

I have the following definition:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\SomeClass;

class SomeProvider extends ServiceProvider
protected $defer = true;

public function register()
$this->app->bind(SomeClass::class, function ($app)
return new SomeClass();

public function provides()
die("This never gets called");
return [SomeClass::class];

And it returns an instance of
as expected, except that according to the documentation, if
is true then the
method should be called. No matter what I set
to, and no matter if I actually ask for an instance of
or not,
is never called.

The way I'm asking for an instance of the class is as follows:



Short answer:
Your compiled manifest file is already compiled by framework.

On the first time when Laravel build the application (and resolves all ofservices providers in IoC) it writes a cached file called services.php (that is, the manifest file, placed in: bootstrap/cache/services.php). So, if you clear the compiled via php artisan clear-compiled command it should force framework to rebuild the manifest file and you could to note that provides method is called. On the next calls/requests provides method is not called anymore.

The sequence of framework boot is nearly like this:

$app = new Illuminate\Foundation\Application(

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
                    # where $bootstrapper is a item from \Illuminate\Foundation\Http\Kernel::$bootstrappers 
                    # and $this is instance of \Illuminate\Foundation\Application

One of bootstrappers is Illuminate\Foundation\Bootstrap\RegisterProviders which invokes \Illuminate\Foundation\Application::registerConfiguredProviders() and then invokes \Illuminate\Foundation\ProviderRepository::__construct() and finally:


When \Illuminate\Foundation\ProviderRepository::load() is called all services providers is registered and \Illuminate\Support\ServiceProvider::provides() are called also well.

And here is the snippet you should know (from \Illuminate\Foundation\ProviderRepository::load):

     * Register the application service providers.
     * @param  array  $providers
     * @return void
    public function load(array $providers)
        $manifest = $this->loadManifest();

        // First we will load the service manifest, which contains information on all
        // service providers registered with the application and which services it
        // provides. This is used to know which services are "deferred" loaders.
        if ($this->shouldRecompile($manifest, $providers)) {
            $manifest = $this->compileManifest($providers);

        // Next, we will register events to load the providers for each of the events
        // that it has requested. This allows the service provider to defer itself
        // while still getting automatically loaded when a certain event occurs.
        foreach ($manifest['when'] as $provider => $events) {
            $this->registerLoadEvents($provider, $events);

        // We will go ahead and register all of the eagerly loaded providers with the
        // application so their services can be registered with the application as
        // a provided service. Then we will set the deferred service list on it.
        foreach ($manifest['eager'] as $provider) {


\Illuminate\Foundation\ProviderRepository::compileManifest() is the place where your provides() method is performed.