覆盖 Laravel 容器中的单例
Override Singleton in Laravel Container
我想知道是否有一种简单的方法可以覆盖 Laravel 框架核心中的单例服务集?
例如我正在尝试使用以下提供商重写 app:name 命令服务“”:
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。)
我看了这个案子,好像不简单。如果您在自定义提供程序中使用 singleton
,它将最终被默认提供程序(延迟的提供程序)覆盖,所以它似乎不会是这样。
检查简单的方法行不通后,在这种情况下你需要做的是分析Laravel注册这个命令时发生了什么。
因此,在您的情况下,您首先搜索 command.app.name
- 您会看到它在 Illuminate\Foundation\Providers\ArtisanServiceProvider
中,并且存在您可能想要覆盖的方法 registerAppNameCommand
。
所以现在您查找 ArtisanServiceProvider
的出现以查看它的启动位置 - 您会看到它在 $providers
属性 中的 Illuminate\Foundation\Providers\ConsoleSupportServiceProvider
中(您可能希望变化)。
所以最后你应该寻找 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
扩展,您在 singleton
中使用自定义 class 覆盖 registerAppNameCommand
使用这种方式您将实现您的目标(我已经验证自定义 class 将被使用 运行 命令 php artisan app:name
)。
或者您可能希望在您的自定义 ArtisanServiceProvider
中从 $devCommands
中删除 'AppName' => 'command.app.name',
并使用您的自定义服务提供商,就像您在注册单身人士的地方所显示的那样,但我还没有尝试过这个方法。
实际上有一种更简洁的方法可以做到这一点。你基本上想扩展一个核心绑定,这可以通过使用 extend
方法来实现:
$this->app->extend('command.app.name', function ($command, $app) {
return new AppNameCommand($app['composer'], $app['files']);
});
Jason Lewis has a really nice article regarding Laravel's IoC on Tutsplus。请务必检查一下 ;)
我想知道是否有一种简单的方法可以覆盖 Laravel 框架核心中的单例服务集?
例如我正在尝试使用以下提供商重写 app:name 命令服务“”:
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。)
我看了这个案子,好像不简单。如果您在自定义提供程序中使用 singleton
,它将最终被默认提供程序(延迟的提供程序)覆盖,所以它似乎不会是这样。
检查简单的方法行不通后,在这种情况下你需要做的是分析Laravel注册这个命令时发生了什么。
因此,在您的情况下,您首先搜索 command.app.name
- 您会看到它在 Illuminate\Foundation\Providers\ArtisanServiceProvider
中,并且存在您可能想要覆盖的方法 registerAppNameCommand
。
所以现在您查找 ArtisanServiceProvider
的出现以查看它的启动位置 - 您会看到它在 $providers
属性 中的 Illuminate\Foundation\Providers\ConsoleSupportServiceProvider
中(您可能希望变化)。
所以最后你应该寻找 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
扩展,您在singleton
中使用自定义 class 覆盖
registerAppNameCommand
使用这种方式您将实现您的目标(我已经验证自定义 class 将被使用 运行 命令 php artisan app:name
)。
或者您可能希望在您的自定义 ArtisanServiceProvider
中从 $devCommands
中删除 'AppName' => 'command.app.name',
并使用您的自定义服务提供商,就像您在注册单身人士的地方所显示的那样,但我还没有尝试过这个方法。
实际上有一种更简洁的方法可以做到这一点。你基本上想扩展一个核心绑定,这可以通过使用 extend
方法来实现:
$this->app->extend('command.app.name', function ($command, $app) {
return new AppNameCommand($app['composer'], $app['files']);
});
Jason Lewis has a really nice article regarding Laravel's IoC on Tutsplus。请务必检查一下 ;)