PHP的Yii框架中创建视图和渲染视图的方法详解
视图是MVC模式中的一部分。它是展示数据到终端用户的代码,在网页应用中,根据视图模板来创建视图,视图模板为PHP脚本文件,主要包含HTML代码和展示类PHP代码,通过yii\web\View应用组件来管理,该组件主要提供通用方法帮助视图构造和渲染,简单起见,我们称视图模板或视图模板文件为视图。
创建视图
如前所述,视图为包含HTML和PHP代码的PHP脚本,如下代码为一个登录表单的视图,可看到PHP代码用来生成动态内容如页面标题和表单,HTML代码把它组织成一个漂亮的HTML页面。
<?php useyii\helpers\Html; useyii\widgets\ActiveForm; /*@var$thisyii\web\View*/ /*@var$formyii\widgets\ActiveForm*/ /*@var$modelapp\models\LoginForm*/ $this->title='Login'; ?> <h1><?=Html::encode($this->title)?></h1> <p>Pleasefilloutthefollowingfieldstologin:</p> <?php$form=ActiveForm::begin();?> <?=$form->field($model,'username')?> <?=$form->field($model,'password')->passwordInput()?> <?=Html::submitButton('Login')?> <?phpActiveForm::end();?>
在视图中,可访问$this指向yii\web\View来管理和渲染这个视图文件。
除了$this之外,上述示例中的视图有其他预定义变量如$model,这些变量代表从控制器或其他触发视图渲染的对象传入到视图的数据。
技巧:将预定义变量列到视图文件头部注释处,这样可被IDE编辑器识别,也是生成视图文档的好方法。
安全
当创建生成HTML页面的视图时,在显示之前将用户输入数据进行转码和过滤非常重要,否则,你的应用可能会被跨站脚本攻击。
要显示纯文本,先调用yii\helpers\Html::encode()进行转码,例如如下代码将用户名在显示前先转码:
<?php useyii\helpers\Html; ?> <divclass="username"> <?=Html::encode($user->name)?> </div>
要显示HTML内容,先调用yii\helpers\HtmlPurifier过滤内容,例如如下代码将提交内容在显示前先过滤:
<?php useyii\helpers\HtmlPurifier; ?> <divclass="post"> <?=HtmlPurifier::process($post->text)?> </div>
技巧:HTMLPurifier在保证输出数据安全上做的不错,但性能不佳,如果你的应用需要高性能可考虑缓存过滤后的结果。
组织视图
与控制器和模型类似,在组织视图上有一些约定:
控制器渲染的视图文件默认放在@app/views/ControllerID目录下,其中ControllerID对应控制器ID,例如控制器类为PostController,视图文件目录应为@app/views/post,控制器类PostCommentController对应的目录为@app/views/post-comment,如果是模块中的控制器,目录应为yii\base\Module::basePath模块目录下的views/ControllerID目录;
对于小部件渲染的视图文件默认放在WidgetPath/views目录,其中WidgetPath代表小部件类文件所在的目录;
对于其他对象渲染的视图文件,建议遵循和小部件相似的规则。
可覆盖控制器或小部件的yii\base\ViewContextInterface::getViewPath()方法来自定义视图文件默认目录。
渲染视图
可在控制器,小部件,或其他地方调用渲染视图方法来渲染视图,该方法类似以下格式:
/** *@paramstring$view视图名或文件路径,由实际的渲染方法决定 *@paramarray$params传递给视图的数据 *@returnstring渲染结果 */ methodName($view,$params=[])
控制器中渲染
在控制器中,可调用以下控制器方法来渲染视图:
- yii\base\Controller::render():渲染一个视图名并使用一个布局返回到渲染结果。
- yii\base\Controller::renderPartial():渲染一个视图名并且不使用布局。
- yii\web\Controller::renderAjax():渲染一个视图名并且不使用布局,并注入所有注册的JS/CSS脚本和文件,通常使用在响应AJAX网页请求的情况下。
- yii\base\Controller::renderFile():渲染一个视图文件目录或别名下的视图文件。
例如:
namespaceapp\controllers; useYii; useapp\models\Post; useyii\web\Controller; useyii\web\NotFoundHttpException; classPostControllerextendsController { publicfunctionactionView($id) { $model=Post::findOne($id); if($model===null){ thrownewNotFoundHttpException; } //渲染一个名称为"view"的视图并使用布局 return$this->render('view',[ 'model'=>$model, ]); } }
小物件
小物件是CWidget或其子类的实例.它是一个主要用于表现数据的组件.小物件通常内嵌于一个视图来产生一些复杂而独立的用户界面.例如,一个日历小物件可用于渲染一个复杂的日历界面.小物件使用户界面更加可复用.
我们可以按如下视图脚本来使用一个小物件:
<?php$this->beginWidget('path.to.WidgetClass');?> ...可能会由小物件获取的内容主体... <?php$this->endWidget();?>
或者
<?php$this->widget('path.to.WidgetClass');?>
后者用于不需要任何body内容的组件.
小物件可通过配置来定制它的表现.这是通过调用CBaseController::beginWidget或CBaseController::widget设置其初始化属性值来完成的.例如,当使用CMaskedTextField小物件时,我们想指定被使用的mask(可理解为一种输出格式,译者注).我们通过传递一个携带这些属性初始化值的数组来实现.这里的数组的键是属性的名称,而数组的值则是小物件属性所对应的值.正如以下所示:
<?php $this->widget('CMaskedTextField',array( 'mask'=>'99/99/9999' )); ?>
继承CWidget并覆盖其init()和run()方法,可以定义一个新的小物件:
classMyWidgetextendsCWidget { publicfunctioninit() { //此方法会被CController::beginWidget()调用 } publicfunctionrun() { //此方法会被CController::endWidget()调用 } }
小物件可以像一个控制器一样拥有它自己的视图.默认情况下,小物件的视图文件位于包含了小物件类文件目录的views子目录之下.这些视图可以通过调用CWidget::render()渲染,这一点和控制器很相似.唯一不同的是,小物件的视图没有布局文件支持。另外,小物件视图中的$this指向小物件实例而不是控制器实例。
视图中渲染
可以在视图中渲染另一个视图,可以调用yii\base\View视图组件提供的以下方法:
- yii\base\View::render():渲染一个视图名.
- yii\web\View::renderAjax():渲染一个视图名并注入所有注册的JS/CSS脚本和文件,通常使用在响应AJAX网页请求的情况下。
- yii\base\View::renderFile():渲染一个视图文件目录或别名下的视图文件。
例如,视图中的如下代码会渲染该视图所在目录下的_overview.php视图文件,记住视图中$this对应yii\base\View组件:
<?=$this->render('_overview')?>
其他地方渲染
在任何地方都可以通过表达式Yii::$app->view访问yii\base\View应用组件,调用它的如前所述的方法渲染视图,例如:
//显示视图文件"@app/views/site/license.php" echo\Yii::$app->view->renderFile('@app/views/site/license.php');