Override Singleton in Laravel Container

I am wondering if there is an easy way to override the singleton services set at the core of the Laravel framework?

eg. I am trying to rewrite the application: command command name '' with the following provider:

use Hexavel\Console\AppNameCommand; use Illuminate\Console\Events\ArtisanStarting; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Support\ServiceProvider; class NameCommandProvider extends ServiceProvider { /** * Register any other events for your application. * * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ public function boot(Dispatcher $events) { $events->listen(ArtisanStarting::class, function ($event) { $event->artisan->resolve('command.app.name'); }, -1); } /** * Register the service provider. * * @return void */ public function register() { $this->app->singleton('command.app.name', function ($app) { return new AppNameCommand($app['composer'], $app['files']); }); } } 

I work 100% because of extensive checks, no matter what order I place with my service provider (above or below ConsoleSupportServiceProvider), it still loads the original AppNameCommand on top of my custom one.

I already have a BUT job , would it be nice to learn about the behavior of singleton services for the future, if at all possible? (This uses Laravel 5.2, if that matters.)

+7
php laravel laravel-5 artisan
source share
2 answers

This is actually a cleaner way to do this. You basically want to extend the kernel binding, which can be achieved using the extend method:

 $this->app->extend('command.app.name', function ($command, $app) { return new AppNameCommand($app['composer'], $app['files']); }); 

Jason Lewis has a really good article on Laravel IoC on Tutsplus . Be sure to check this out;)

+7
source share

I looked at this case, and it seems that it is not easy. If you use singleton in your custom Provider, it will finally be overridden by the default provider (deferred), so it seems like it is not.

After verifying that the simple approach does not work, you need to analyze in this case what happens when Laravel registers this command.

So, in your case, you are first looking for command.app.name - you see it in Illuminate\Foundation\Providers\ArtisanServiceProvider , and there is a registerAppNameCommand method that you would probably override.

So now you are looking for an entry of ArtisanServiceProvider to see where it was launched - you see it in the Illuminate\Foundation\Providers\ConsoleSupportServiceProvider in the $providers property (which you probably want to change).

So, you should look for entries of ConsoleSupportServiceProvider , and you see it in config/app.php .

So what you need to do in this case:

  • Change config/app.php - change Illuminate\Foundation\Providers\ConsoleSupportServiceProvider to your own ConsoleSupportServiceProvider
  • In your custom version, you should go from \Illuminate\Foundation\Providers\ConsoleSupportServiceProvider , but change $providers from Illuminate\Foundation\Providers\ArtisanServiceProvider to your ArtisanServiceProvider
  • finally, create a custom ArtisanServiceProvider that will expand from \Illuminate\Foundation\Providers\ArtisanServiceProvider , where you redefine registerAppNameCommand using your own class in singleton

Using this method, you will achieve your goal (I checked that the user class will be used with the php artisan app:name command).

Alternatively, you may want to create your own ArtisanServiceProvider remove 'AppName' => 'command.app.name', from $devCommands and use your specialized service provider, as you showed where you register your singleton, but I have not tried this approach .

+5
source share

All Articles