如何覆盖Laravel 4中的View::make()


How to override View::make() in Laravel 4?

我想覆盖Laravel中的默认View::make()方法,该方法可用于向用户返回视图响应。

(我想)我已经发现这个方法存储在Illuminate'View'Factory.php中,我一直在阅读IoC容器的相关内容,同时尝试使用一些类似的教程使其发挥作用,但它就是不起作用。

我已经创建了一个文件App'Lib'MyProject'Extensions'View'Factory.php,其中包含以下代码:

<?php namespace MyProject'Extensions'View;
use Illuminate'View'Factory as OldFactory;
class Factory extends OldFactory {
    public static function make() {
        // My own implementation which should override the default
    }
}

其中MyProject文件夹是用Composer自动加载的。但是,每当调用View(特别是View::make())的静态方法时,我不知道如何使用Factory类的"修改"版本。如果能帮上忙就太好了!

谢谢!

用Laravel的话说,对View::make的调用就是对View门面的调用。Facades提供对服务容器中的服务的全局静态访问。步骤1是查找实际类别View指向

#File: app/config/app.php
'aliases' => array(
    'View'            => 'Illuminate'Support'Facades'View',
)

这意味着CCD_ 11被别名为类CCD_。如果你看看Illuminate'Support'Facades'View 的来源

#File: vendor/laravel/framework/src/Illuminate/Support/Facades/View.php
class View extends Facade {
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'view'; }
}

您可以看到facade服务访问器是view。这意味着呼叫

View::make...

(或多或少)相当于对的调用

$app = app();
$app['view']->make(...

也就是说,facade提供对服务容器中view服务的访问。要交换出不同的类,所需要做的就是将不同的对象绑定为view服务。Laravel为此提供了一种extend方法。

App::extend('view', function(){
    $app = app();
    // Next we need to grab the engine resolver instance that will be used by the
    // environment. The resolver will be used by an environment to get each of
    // the various engine implementations such as plain PHP or Blade engine.
    $resolver = $app['view.engine.resolver'];
    $finder = $app['view.finder'];
    $env = new 'MyProject'Extensions'View($resolver, $finder, $app['events']);
    // We will also set the container instance on this view environment since the
    // view composers may be classes registered in the container, which allows
    // for great testable, flexible composers for the application developer.
    $env->setContainer($app);
    $env->share('app', $app);
    return $env;                
});

请注意,这不仅仅是实例化一个对象。我们需要以与原始视图服务实例化和绑定相同的方式对其进行实例化(通常使用bindbindShared)。你可以在这里找到这个代码

#File: vendor'laravel'framework'src'Illuminate'View'ViewServiceProvider.php
public function registerFactory()
{
    $this->app->bindShared('view', function($app)
    {
        // Next we need to grab the engine resolver instance that will be used by the
        // environment. The resolver will be used by an environment to get each of
        // the various engine implementations such as plain PHP or Blade engine.
        $resolver = $app['view.engine.resolver'];
        $finder = $app['view.finder'];
        $env = new Factory($resolver, $finder, $app['events']);
        // We will also set the container instance on this view environment since the
        // view composers may be classes registered in the container, which allows
        // for great testable, flexible composers for the application developer.
        $env->setContainer($app);
        $env->share('app', $app);
        return $env;
    });
}

你可以测试你的绑定是否适用于像这样的代码

var_dump(get_class(app()['view']));

你应该看看你的类名。一旦你确定绑定已经"完成",你就可以自由地重新定义你想要的任何方法。