Мне интересно, есть ли простой способ переопределить набор одноэлементных сервисов в ядре платформы Laravel?
например Я пытаюсь переписать приложение: name command service » со следующим поставщиком:
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']);
});
}
}
Я на 100% все работаю из-за обширных проверок, независимо от того, в каком порядке я поставил своего поставщика услуг (выше или ниже ConsoleSupportServiceProvider), он по-прежнему загружает исходную команду AppNameCommand поверх моей пользовательской.
У меня уже есть работа вокруг НО было бы неплохо узнать о поведении синглтон-сервисов в будущем, если это вообще возможно? (Это использует Laravel 5.2, если это что-то меняет.)
На самом деле есть более чистый способ сделать это. В основном вы хотите расширить привязку ядра, чего можно добиться с помощью extend
метод:
$this->app->extend('command.app.name', function ($command, $app) {
return new AppNameCommand($app['composer'], $app['files']);
});
Джейсон Льюис есть действительно хорошая статья о IoC Laravel на Tutsplus. Не забудьте проверить это;)
Я посмотрел на этот случай, и, кажется, он не из легких. Если вы используете singleton
в вашем пользовательском провайдере он будет окончательно переопределен провайдером по умолчанию (отложенным), так что, похоже, это не так.
После проверки, что этот простой подход не работает, в этом случае вам нужно проанализировать, что происходит, когда Laravel регистрирует эту команду.
Так что в вашем случае вы ищете сначала command.app.name
— Вы видите, что это в Illuminate\Foundation\Providers\ArtisanServiceProvider
и есть метод registerAppNameCommand
Вы хотели бы, вероятно, переопределить.
Так что теперь вы ищите случаи ArtisanServiceProvider
чтобы увидеть, где он запущен — вы видите, что в Illuminate\Foundation\Providers\ConsoleSupportServiceProvider
в $providers
свойство (которое вы хотели бы изменить).
Итак, наконец, вы должны искать вхождения ConsoleSupportServiceProvider
и вы видите, что это в config/app.php
,
Итак, что вам нужно сделать в этом случае:
config/app.php
— менять Illuminate\Foundation\Providers\ConsoleSupportServiceProvider
в ваш собственный ConsoleSupportServiceProvider
\Illuminate\Foundation\Providers\ConsoleSupportServiceProvider
но изменить в $providers
от Illuminate\Foundation\Providers\ArtisanServiceProvider
в ваш обычай ArtisanServiceProvider
ArtisanServiceProvider
который простирается от \Illuminate\Foundation\Providers\ArtisanServiceProvider
где вы переопределите registerAppNameCommand
используя пользовательский класс в singleton
Используя этот способ, вы достигнете своей цели (я убедился, что пользовательский класс будет использоваться при выполнении команды php artisan app:name
).
В качестве альтернативы вы можете захотеть ArtisanServiceProvider
Удалить 'AppName' => 'command.app.name',
от $devCommands
и используйте своего поставщика услуг, как вы показали, где вы регистрируете свой синглтон, но я не пробовал этот подход.