Yii2添加到头()和尾体()中
在开发一个可以有多个前端主题的站点时,我正在寻找一种方法,允许后端用户手动将代码注入头部和身体。两个用例如下所示:Yii2添加到头()和尾体()中,yii2,Yii2,在开发一个可以有多个前端主题的站点时,我正在寻找一种方法,允许后端用户手动将代码注入头部和身体。两个用例如下所示: <?php $this->endBody() ?> <?= $this->params['theme_include_body_end'] ?> 案例1-风格 在后端,用户选择一个主题 用户喜欢的主题,但想使链接不同的颜色 用户可以将自定义代码设置为在标记末尾执行,而不是复制和修改主题 案例2-脚本 用户希望将自定义JavaScript添加到文
<?php $this->endBody() ?>
<?= $this->params['theme_include_body_end'] ?>
案例1-风格
标记末尾执行,而不是复制和修改主题registerCss
和registerJs
来完成,但它们会自动将传递给它们的任何内容包装在
或
标记中。我希望有一种方法可以直接将指示的内容直接注入head()
或endBody()
方法。这背后的原因是,我不希望限制用户可以注入的内容(可能头部需要一个脚本标记)
目前,我只是将要添加的代码存储在params中,然后手动将其包含在每个主题中,如下所示:
<?php $this->endBody() ?>
<?= $this->params['theme_include_body_end'] ?>
这是不可取的,因为在创建主题时很容易忘记。我想找到一种方法,将我的param值自动附加到endBody()调用中,这样无论何时调用endBody(),都会包含我的代码(与head()调用相同)。您可以使用自己的视图组件来覆盖方法
renderhadtml()
和renderBodyEndHtml()
。在这些方法中,可以根据需要注入必要的代码:
namespace common/components;
class View extends \yii\web\View {
/**
* @var string Content that should be injected to end of `<head>` tag
*/
public $injectToHead = '';
/**
* @var string Content that should be injected to end of `<body>` tag
*/
public $injectToBodyEnd = '';
/**
* @inheritdoc
*/
protected function renderHeadHtml()
{
return parent::renderHeadHtml() . $this->injectToHead;
}
/**
* @inheritdoc
*/
protected function renderBodyEndHtml($ajaxMode)
{
return parent::renderBodyEndHtml(ajaxMode) . $this->injectToBodyEnd;
}
}
控制器代码中的某个地方:
\Yii::$app->view->injectToHead = '...';
\Yii::$app->view->injectToBodyEnd = '...';
Yii2已经通过使用在视图类中提供了此功能 您需要两个简单的步骤: 1-(在所需视图文件中):在任何给定视图中
<?php $this->beginBlock('block1'); ?>
...content of block1...
<?php $this->endBlock(); ?>
...
<?php $this->beginBlock('block3'); ?>
...content of block3...
<?php $this->endBlock(); ?>
…block1的内容。。。
...
…block3的内容。。。
2-(在布局中):定义块名及其在布局页面中的位置
...
<?php if (isset($this->blocks['block1'])): ?>
<?= $this->blocks['block1'] ?>
<?php else: ?>
... default content for block1 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block2'])): ?>
<?= $this->blocks['block2'] ?>
<?php else: ?>
... default content for block2 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block3'])): ?>
<?= $this->blocks['block3'] ?>
<?php else: ?>
... default content for block3 ...
<?php endif; ?>
...
。。。
... block1的默认内容。。。
...
... block2的默认内容。。。
...
... block3的默认内容。。。
...
参考:Yii2指南
我希望这能帮助别人。谢谢。根据您的用例,另一个可能更简单的选择是使用查看事件。您可以在页面的不同部分插入不同的项目。例如:
Yii::$app->view->on(View::EVENT_END_BODY, function () {
echo date('Y-m-d');
});
您可以在这里阅读更多内容:这是一个很好的开始,但当我尝试用我的模块实现它时,它崩溃了。因为有一个后端和前端模块,我不能在组件级别设置视图,否则它将应用于这两个模块。我需要在模块内设置视图类。如果这样做,则无法从控制器设置injectToHeadEnd属性。有没有想过在使用多个模块时调整此设置?我不理解您的问题:为什么不能设置?)您的控制器不在模块中?控制器在模块中,但配置文件适用于整个应用程序。我想我成功了。我必须在模块init()中设置视图类,如下所示:
Yii::$app->components=['view'=>['class'=>'\common\components\view']
然后,我可以按照您的指示设置注入的代码,但是,因为我在重写模块中的视图,我的IDE抱怨它是一个未定义的字段。虽然IDE认为它是未定义的,但它仍然有效。如果您不想全局设置组件,您可以使用\yii\base\controller::setView
为必要的控制器定义自己的视图。此外,您可以创建自己的父控制器类并重写\yii\base\controller::getView
方法(此方法默认返回yii::$app->view;
)。非常好,谢谢!正是我需要的。感谢我喜欢此解决方案,因为endBody()引发此事件,因此它直接绑定到其中,不需要扩展任何类,也不需要布局是否实现某些参数或块解决方案。请注意,如果您在从视图调用的某个对象上使用它,则需要将调用放在事件注册器函数endBody()之前或者beginBody()等等,因为如果您将事件放置在此调用之后,它将已经触发