Кэширование вывода вида в 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 своей собственной.
шаги, которые я бы предпринял:
- создать библиотека/пакет. Цель состоит в том, чтобы создать класс, который расширяет логику представления Laravel. После того, как вы посмотрите, вы можете расширить этот - это
View
фасад - если вы расширили вид фасада с вашим собственным (ака, если мое предположение о файле в шаге 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-страница. Это обеспечит существенный прирост скорости вашего приложения, так как кэш вашей страницы обновляется только при изменении отображаемых данных.
кэшировать все авторизованные страницы в приложении через