在Laravel服务提供商中更换服务的最佳方法是什么?

Den*_*ins 5 php laravel

我想将Laravel框架提供的服务替换为我自己的服务,扩展相同的Laravel服务.在这种特定情况下,我想交换BladeCompiler服务.

ViewServiceProviderLaravel提供的默认设置如下:

use Illuminate\View\Engines\BladeCompiler;
use Illuminate\View\Engines\CompilerEngine;

...

public function registerBladeEngine($resolver)
{
    $app = $this->app;

    $resolver->register('blade', function() use ($app)
    {
        $cache = $app['path.storage'].'/views';

        $compiler = new BladeCompiler($app['files'], $cache);

        return new CompilerEngine($compiler, $app['files']);
    });
}
Run Code Online (Sandbox Code Playgroud)

我唯一需要做的是扩展提供程序,重写方法并替换编译器类.在这种情况下,My\View\Engines\BladeCompiler.

但要做到这一点,我必须将所有函数复制并粘贴到我的服务提供者,并只需替换该use语句.这是一种糟糕的方式,因为对Laravel那部分的任何修改都会破坏我的应用程序.

我真正想要做的是创建另一个扩展默认刀片编译器类的类,以便为它添加更多功能.

有没有人有更好的主意?

编辑:

我打开了一个描述该问题的问题,Taylor将对4.1进行更改,这使得扩展服务变得更加容易(至少是刀片编译器).

Ake*_*rts 4

我相信你有两个选择:

  1. 用您自己的服务提供商覆盖服务提供商。
  2. 利用 BladeCompiler 的extend()方法。

选项 1:服务提供商复制和粘贴

您要做的关键是用您的扩展版本覆盖 Blade 编译器。由于整个继承问题,您必须以与默认服务提供者几乎完全相同的方式定义它;特别是这段代码:

$resolver->register('blade', function() use ($app)
{
    $cache = $app['path.storage'].'/views';

    // This is where your extended class would go.
    $compiler = new BladeCompiler($app['files'], $cache);

    return new CompilerEngine($compiler, $app['files']);
});
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式访问服务提供者中的 View 类的 EngineResolver:

$this->app['view']->getEngineResolver()
Run Code Online (Sandbox Code Playgroud)

所有这些放在一起,您将得到以下内容(替换类名并use在适当的地方进行修改):

<?php

use Illuminate\Support\ServiceProvider;
use Illuminate\View\Engines\CompilerEngine;

class ExtendBladeServiceProvider extends ServiceProvider {

    public function register()
    {
        $resolver = $this->app['view']->getEngineResolver();

        $resolver->register('blade', function() use ($app)
        {
            $cache = $app['path.storage'].'/views';

            $compiler = new MyBladeCompiler($app['files'], $cache);

            return new CompilerEngine($compiler, $app['files']);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

所以是的,您基本上是在复制现有服务提供商的代码。但据我所知,你几乎必须这样做。我不知道你为什么担心 Laravel 的变化会阻碍你的应用程序;您实际上依赖于 Laravel 组件,因此任何更改都可能会破坏事物。这是您使用无法控制的组件所冒的风险。

选项2:BladeCompiler 的extend()方法。

您几乎可以在应用程序中任何有意义的地方执行此操作。您不会BladeCompiler以传统的方式扩展该类,但您可以实现自己的一组编译函数来运行。

extend()将提供的闭包添加到编译期间迭代的数组中。它本质上与扩展类方法相同,并且不需要您重新实例化诸如 CompileEngine 之类的东西。

注册这些扩展的一种选择是使用服务提供商的boot()方法(您register()也可以使用,只需确保按照正确的顺序进行即可):

public function boot()
{
    $blade = $this->app['view']->getEngineResolver()->resolve('blade')->getCompiler();

    $blade->extend(function($value) use ($blade)
    {
        $matcher = $blade->createMatcher('myfeature');

        return preg_replace($matcher, '<?php echo MyFeature::make$2; ?>', $value);
    });
}
Run Code Online (Sandbox Code Playgroud)