又快又脏
好吧,我相信您知道,一种选择是在渲染视图时将项目缓存在控制器内。我怀疑你不想这样做,因为从长远来看它的可维护性较差。
更可维护(?)的方法
但是,如果视图加载器/渲染器没有在您想要的位置触发事件,您可以创建一个。因为 Laravel 4 中的每个包/库都是在 App 容器中设置的,所以您实际上可以用自己的库替换 View 库。
我要采取的步骤是:
- 创建一个库/包。目标是创建一个扩展 Laravel 视图逻辑的类。看完之后,您可能想要扩展this one https://github.com/laravel/framework/blob/master/src/Illuminate/View/Environment.php- 这是
View
facade
- 如果您用自己的视图外观扩展(也就是说,如果我在步骤 1 中对文件的假设是正确的),那么您只需要替换视图的别名 https://github.com/laravel/laravel/blob/master/app/config/app.php#L180 in
app/config/app.php
与你自己的。
编辑-我玩了一下这个。虽然我不一定同意缓存 View 结果,而不是缓存 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
正面。在我们的例子中,这意味着我们将延长照明\视图\环境 https://github.com/laravel/framework/blob/master/src/Illuminate/View/Environment.php.
在此类中,我们将获取正在呈现的视图的结果,并添加一些逻辑来缓存(或不缓存)它。这是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
类作为 Facade 工作。我有一篇关于创建 Laravel 外观 http://fideloper.com/create-facade-laravel-4。在这种情况下,如何实现这一点的方法如下:
为我们的新环境创建立面。我们将其命名为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
class.
<?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 的视图外观。编辑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()
method!
Finally
值得注意的是,每个 Web 请求的多个“请求”中都会加载一些模式。以 Symfony 为例,让您将控制器定义为服务器 http://symfony.com/doc/current/cookbook/controller/service.html。 Zend 有(有?)一个 Action Stacks 的概念,它让你
...有效地帮助您创建要在请求期间执行的[控制器]操作队列。
也许您想在 Laravel 中探索这种可能性,并缓存这些“操作”的结果(相对于直接缓存视图)。
只是一个想法,不是建议。