Кэширование вывода вида в Laravel 4

Я знаю, что Blade уже кэширует скомпилированный PHP для всех представлений blade, но я хотел бы сделать этот шаг дальше. Сайт, который я работаю над модульным видом на компонент, а затем собрана в контроллер по умолчанию. Каждый из" виджетов " имеет свой собственный вид, который редко изменяет контент (за исключением нескольких часто обновляемых). Итак, я хотел бы кэшировать вывод HTML этих редко меняющихся представлений, чтобы предотвратить их оценку на каждой странице нагрузка.

в Laravel 3 мы могли бы сделать что-то вроде этого (кредитные форумы Laravel):

Event::listen(View::loader, function($bundle, $view)
{
  return Cache::get($bundle.'::'.$view, View::file($bundle, $view, 
                                                  Bundle::path($bundle).'view'));
});

к сожалению, View::loader полностью исчез в Laravel 4. При копании IlluminateViewView и IlluminateViewEnvironment, я обнаружил, что каждое представление отправляет событие с именем "composing: {view_name}". Прослушивание этого события предоставляет имя представления и данные, передаваемые ему при каждом отображении представления, однако возврат из обратного вызова не имеет того же эффекта, что и в Laravel 3:

Event::listen('composing: *', function($view) {
  if(!in_array($view->getName(), Config::get('view.alwaysFresh'))) {
    // Hacky way of removing data that we didn't pass in
    // that have nasty cyclic references (like __env, app, and errors)
    $passedData = array_diff_key($view->getData(), $view->getEnvironment()
                                                                  ->getShared());

    return Cache::forever($view->getName() . json_encode($passedData), function() {
      return 'test view data -- this should appear in the browser';
    });
}, 99);

вышеуказанное не обходит нормальный взгляд включая и процесс перевода.

Итак, как вы можете обойти обычный просмотр рендеринга и вернуть кэшированное содержимое из этого события составления? Это сейчас можно в фреймворк Laravel без некоторые уродливые ничтожества?

2 ответов


и

Ну, один из вариантов, как я уверен, вы знаете, заключается в кэшировании элементов внутри контроллеров по мере отображения представления. Я подозреваю, что вы не хотите этого делать, так как в долгосрочной перспективе это менее ремонтопригодно.

более ремонтопригодны(?) метод

однако, если загрузчик/визуализатор представления не запускает событие там, где вы хотите, вы можете его создать. Потому что каждый пакет / библиотека в Laravel 4 установлен в приложении контейнер, вы можете фактически заменить библиотеку View своей собственной.

шаги, которые я бы предпринял:

  1. создать библиотека/пакет. Цель состоит в том, чтобы создать класс, который расширяет логику представления Laravel. После того, как вы посмотрите, вы можете расширить этот - это View фасад
  2. если вы расширили вид фасада с вашим собственным (ака, если мое предположение о файле в шаге 1 Правильно), вам просто нужно заменить псевдоним для просмотра на app/config/app.php С вашим собственным.

Edit - я немного поиграл с этим. Хотя я не обязательно согласен с кэшированием результата представления, против кэширования sql-запросов или "более тяжелых подъемов", вот как я бы сделал это в Laravel 4:

рендеринг представления в Laravel 4 не запускает событие, которое позволяет нам кэшировать результат представления. Вот как я добавил в эту функциональность, чтобы кэшировать представления результат.

вы можете рассмотреть последствия кэширования результата представления. Например, это не обходится тяжелой работой по разговору с базой данных, чтобы получить данные, необходимые для представления. В любом случае, это дает хороший обзор по расширению или замене основных элементов.

сначала создайте пакет и настройте его автоматическую загрузку. Я буду использовать пространство имен Fideloper\View. Это автозапуск в composer.json будет похоже это:

"autoload": {
    "classmap": [
        "app/commands",
        "app/controllers",
        "app/models",
        "app/database/migrations",
        "app/database/seeds",
        "app/tests/TestCase.php"
    ],
    "psr-0": {
        "Fideloper": "app/"
    }
},

затем создайте класс для замены View фасад. В нашем случае это означает, что мы расширим Подсветка\Вид\Окружающая Среда.

в этом классе мы возьмем результат визуализации представления и добавим некоторую логику для его кэширования (или не кэширования). Вот Fideloper/View/Environment.php:

<?php namespace Fideloper\View;

use Illuminate\View\Environment as BaseEnvironment;
use Illuminate\View\View;

class Environment extends BaseEnvironment {

    /**
     * Get a evaluated view contents for the given view.
     *
     * @param  string  $view
     * @param  array   $data
     * @param  array   $mergeData
     * @return \Illuminate\View\View
     */
    public function make($view, $data = array(), $mergeData = array())
    {
        $path = $this->finder->find($view);

        $data = array_merge($mergeData, $this->parseData($data));

        $newView = new View($this, $this->getEngineFromPath($path), $view, $path, $data);

        // Cache Logic Here

        return $newView;
    }

}

Итак, вот где будет основная часть вашей работы-заполнение этого // Cache Logic Here. Тем не менее, у нас осталось немного сантехники делать.

Далее нам нужно настроить наш новый Environment класс для работы в качестве фасада. У меня есть сообщение в блоге о создание фасадов Laravel. Вот как это сделать в этом случае:

создайте фасад для нашей новой окружающей среды. Мы назовем его fideloper.view в коде.

<?php namespace Fideloper\View;

use Illuminate\Support\Facades\Facade;

class ViewFacade extends Facade {

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'fideloper.view'; }

}

затем создайте поставщика услуг, который скажет Laravel, что создавать, когда fideloper.view называется. Обратите внимание, что это должно имитировать функциональность Illuminate\View\ViewServiceProvider для создание расширенного Environment класса.

<?php namespace Fideloper\View;

use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app['fideloper.view'] = $this->app->share(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 Environment($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;
        });
    }

}

наконец, нам нужно подключить все это вместе и сказать Laravel загрузить нашего поставщика услуг и заменить вид фасада Illuminate на наш собственный. Edit app/config/app.php:

добавить поставщика услуг:

'providers' => array(

    // Other providers

    'Fideloper\View\ViewServiceProvider',

),

замените вид фасада на наш собственный:

'aliases' => array(

    // Other Aliases

    //'View'            => 'Illuminate\Support\Facades\View',
    'View'            => 'Fideloper\View\ViewFacade',

),

затем вы сможете использовать любую логику, вы хотите в View::make() метод!

наконец-то

стоит отметить, что есть некоторые шаблоны для загрузки в нескольких "запросах" на веб-запрос. Symfony, например, давайте вы определите контроллеры как серверы. Зенд (имел?) концепция стеков действий, которые позволяют вам

... эффективно поможет вам создать очередь действий [контроллера] для выполнения во время запроса.

возможно, вы хотели бы изучить, что возможность в Laravel и кэшировать результаты этих "действий" (vs кэширование представления напрямую).

просто мысль, а не рекомендация.


существует библиотека для кэширования представлений / частей в Laravel (и не только) - Flatten.

Это мощная система кэша для кэширования страниц во время выполнения. То, что он делает, довольно просто : вы говорите ему, какая страница должна быть кэширована, когда кэш должен быть сброшен, и оттуда Flatten обрабатывает все это. Он будет спокойно сглаживать ваши страницы в простой HTML и хранить их. Что, если пользователь посещает страницу, которая уже была сплющена, весь PHP highjacked вместо этого отображает простой HTML-страница. Это обеспечит существенный прирост скорости вашего приложения, так как кэш вашей страницы обновляется только при изменении отображаемых данных.

кэшировать все авторизованные страницы в приложении через