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

I would like to override the default method View::make()

in Laravel that can be used to return the view to the user.

(I think) I already figured out that this method is stored internally Illuminate\View\Factory.php

and I was reading about the IoC container trying to get it to work using some similar tutorials , but it just won't work.

I have already created a file App\Lib\MyProject\Extensions\View\Factory.php

containing the following code:

<?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
    }

}

      

where the folder is MyProject

automatically loaded by Composer. But I don't know how to use this "modified" version of the class Factory

whenever a static method is called View

(in particular View::make()

). Some help would be great!

Thank!

+3


source to share


1 answer


Calling View::make

in Laravel talks about calling the facade View

. Facades provide global static access to a service in a service container. Step 1 - Finding the actual class View

points to

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

      

This means it View

is a class alias Illuminate\Support\Facades\View

. If you look at the sourceIlluminate\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'; }

}

      

You can see that the accessory is the service facade View

. This means that the call

View::make...

      

is (more or less) equivalent to calling

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

      



That is, the facade provides access to the service View

in the service container. To replace another class, all you have to do is bind the other object as a service View

. Laravel provides a method extend

for this.

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;                
});

      

Note that this is more than just creating an object. We need to create an instance in the same way that we were created and bound to the original view service (usually with bind

or bindShared

). You can find this code here

#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;
    });
}

      

You can check if your linking worked with code like this

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

      

You should see your class name. Once you are sure that the binding is "taken", you can override any methods you want.

+11


source







All Articles