创建一个自定义视图渲染器

这里有许多PHP模板引擎。Yii2只提供原生PHP模板。如果你想使用一个存在的模板引擎,或者创建你自己的,你需要实现它——当然,如果还没有被Yii社区实现的话。

在本小节中,我们将会重新实现Smarty模板支持。

准备

  1. 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的yii2-app-basic应用。
  2. 安装Smarty库:
  1. composer require smarty/smarty

如何做…

执行如下步骤,创建一个自定义视图渲染器:

  1. 创建smarty/ViewRenderer.php
  1. <?php
  2. namespace app\smarty;
  3. use Smarty;
  4. use Yii;
  5. class ViewRenderer extends \yii\base\ViewRenderer
  6. {
  7. public $cachePath = '@runtime/smarty/cache';
  8. public $compilePath = '@runtime/smarty/compile';
  9. /**
  10. * @var Smarty
  11. */
  12. private $smarty;
  13. public function init()
  14. {
  15. $this->smarty = new Smarty();
  16. $this->smarty->setCompileDir(Yii::getAlias($this->compilePath));
  17. $this->smarty->setCacheDir(Yii::getAlias($this->cachePath));
  18. $this->smarty->setTemplateDir([
  19. dirname(Yii::$app->getView()->getViewFile()),
  20. Yii::$app->getViewPath(),
  21. ]);
  22. }
  23. public function render($view, $file, $params)
  24. {
  25. $templateParams = empty($params) ? null : $params;
  26. $template = $this->smarty->createTemplate($file, null,
  27. null, $templateParams, false);
  28. $template->assign('app', \Yii::$app);
  29. $template->assign('this', $view);
  30. return $template->fetch();
  31. }
  32. }
  1. 现在,我们需要连接这个视图渲染器到应用中。在config/web.php文件中,我们需要添加视图组件的渲染器:
  1. 'components' => [
  2. //....
  3. 'view' => [
  4. 'renderers' => [
  5. 'tpl' => [
  6. 'class' => 'app\smarty\ViewRenderer',
  7. ],
  8. ],
  9. ],
  10. //...
  11. ];
  1. 现在让我们测试它。创建一个新的SmartyController
  1. <?php
  2. namespace app\controllers;
  3. use yii\web\Controller;
  4. class SmartyController extends Controller
  5. {
  6. public function actionIndex()
  7. {
  8. return $this->render('index.tpl', [
  9. 'name' => 'Bond',
  10. ]);
  11. }
  12. }
  1. 接下来,我们需要创建views/smarty/index.tpl视图:
  1. <div class="smarty-index">
  2. <h1>Smarty Example</h1>
  3. <p>Hello, {$name}!</p>
  4. </div>
  1. 尝试访问这个控制器。如果成功的话,你应该能得到如下输出:

创建一个自定义视图渲染器 - 图1

工作原理…

视图渲染器继承了yii\base\ViewRenderer抽象类,并只需要实现一个方法render

  1. <?php
  2. namespace yii\base;
  3. abstract class ViewRenderer extends Component
  4. {
  5. /**
  6. * Renders a view file.
  7. *
  8. * This method is invoked by [[View]] whenever it tries to render a view.
  9. * Child classes must implement this method to render the given view file.
  10. *
  11. * @param View $view the view object used for rendering the file.
  12. * @param string $file the view file.
  13. * @param array $params the parameters to be passed to the view file.
  14. * @return string the rendering result
  15. */
  16. abstract public function render($view, $file, $params);
  17. }

因此,我们会获得一个视图组件、文件路径和渲染变量。我们需要处理这个问题,并返回渲染的结果。在我们的例子中,处理它自己是通过Smarty模板引擎完成的,所以我们需要正确的初始化它,并调用它的处理方法:

  1. class ViewRenderer extends \yii\base\ViewRenderer
  2. {
  3. public $cachePath = '@runtime/smarty/cache';
  4. public $compilePath = '@runtime/smarty/compile';
  5. private $smarty;
  6. public function init()
  7. {
  8. $this->smarty = new Smarty();
  9. $this->smarty->setCompileDir(Yii::getAlias($this->compilePath));
  10. $this->smarty->setCacheDir(Yii::getAlias($this->cachePath));
  11. $this->smarty->setTemplateDir([
  12. dirname(Yii::$app->getView()->getViewFile()),
  13. Yii::$app->getViewPath(),
  14. ]);
  15. }
  16. //…
  17. }

将Yii临时文件存放在应用runtime文件夹中是一个好习惯。这就是为什么我们设置compile文件夹(Smarty存储它的编译为PHP的模板)到runtime/smarty/compile

渲染它自己非常简单:

  1. public function render($view, $file, $params)
  2. {
  3. $templateParams = empty($params) ? null : $params;
  4. $template = $this->smarty->createTemplate($file, null, null,
  5. $templateParams, false);
  6. $template->assign('app', \Yii::$app);
  7. $template->assign('this', $view);
  8. return $template->fetch();
  9. }

通过$this->render设置的数据被传递到Smarty模板。此外,我们创建特殊的Smarty模板变量,名叫appthis,它分别指向Yii:$appYii::$app->view,这允许我们在一个模板内部获取应用属性。

然后,我们就可以渲染这个模板了。

参考

你可以立刻使用带有插件和配置支持的Smarty视图渲染器,在https://github.com/yiisoft/yii2-smarty

为了了解更多关于Smarty和视图渲染器,参考如下地址: