2014-09-23 136 views
3

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

(我认为)我已经想通了,这种方法存储内部Illuminate\View\Factory.php,我一直在阅读有关IoC容器,而试图使它工作使用somesimilartutorials,但它只是将无法正常工作。

我已经创建了一个文件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文件夹自动加载与作曲家。但是我不知道如何在每次调用View(特别是View::make())的静态方法时使用这个'修改'版本的Factory类。一些帮助会很棒!

谢谢!

回答

11

致电View::make在Laravel说,致电View立面。 Facades提供对服务容器中的服务的全局静态访问。步骤1是查找实际的类View指向

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

这意味着View混叠到类Illuminate\Support\Facades\View。如果你看看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'; } 

} 

源可以看到门面服务访问是view。这意味着以

呼叫
View::make... 

是(或多或少)相当于一个呼叫到

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

即,门面提供访问在服务容器中的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'])); 

你应该可以看到你的类名。一旦你确定绑定已经被“取走”,你就可以自由地重新定义你想要的任何方法。

+0

非常感谢,我现在已经有了一切工作。作为最后一个问题:将App :: extend()代码放在/start/global.php文件中是否是一种好的做法?我不太确定把它放在哪里,我认为官方文档指向这个位置...... – user132169 2014-09-24 07:23:16

+0

@ user132169它应该没问题,虽然我认为'start/global.php'将在Laravel 5.0中消失(除非你运行的是旧服务提供商) – 2014-09-24 14:27:10