Yii 视图渲染过程 代码详解

  摘要:初学yii,为了巩固基础,将框架survey过程记录下来,便于记忆。也供初学者一同参考,理解有误之处,请不吝指教。
  通常我们使用yiic自动生成代码框架后,会有这个application.components.Controller控制器类,然后其他自定义的控制器类都继承于这个Controller类,这样便于对所有的控制器进行过滤操作。这是后话。
  这篇博客主要讨论的是,我们在application.controllers.SiteController的actionIndex方法中调用:$this->render(‘index’);在这之后都发生了什么,控制器如何调用了视图,layout文件和模板文件怎么被渲染,它们之间又发生了什么呢,来就看看这个问题是怎么回事。
  

framework/web/CController.php

public function render($view,$data=null,$return=false){
    //先渲染index模板文件
    $output=$this->renderPartial($view,$data,true);
    //根据loyout文件名来寻找layout脚本文件,默认loyout文件是'//layouts/column1'所以肯定能找到,会返回非false,所以这个if能够进入
    if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
        //在这里再次调用renderFile()来渲染layout文件,并且把渲染过的模板文件赋值给$content变量给到layout文件,第三个参数是true,所以返回渲染后的结果,这个$output就是最终layout文件和模板文件渲染后结合到一块的文件
        $output=$this->renderFile($layoutFile,array('content'=>$output),true);
    //什么也不做
    $this->afterRender($view,$output);
    //再次加工一下$output。测试:当在控制器里面这样引入jquery
    //Yii::app()->clientScript->registerCoreScript('jquery');
    //那么下面这个方法就会把jQuery引入的script代码放在$output的里面
    $output=$this->processOutput($output);

    if($return)
        return $output;
    else
        echo $output;
}

public function renderPartial($view,$data=null,$return=false,$processOutput=false){
    //返回给定的view name 对应的view file
    if(($viewFile=$this->getViewFile($view))!==false)
        {
            //渲染这个模板文件(protected/views/site/index.php)
            $output=$this->renderFile($viewFile,$data,true);
            if($processOutput) 
                $output=$this->processOutput($output);
            if($return)
                //第三个参数是true,所以返回渲染后的内容,这个方法结束。
                return $output;
            else
                echo $output;
        }
        else
            throw new CException(Yii::t('yii','{controller} cannot find the requested view "{view}".',
                array('{controller}'=>get_class($this), '{view}'=>$view)));
}



  综上:当控制器调用$this->render()的时候,是先渲染模板文件application.views.site.index.php,然后把渲染以后的结果赋值给layout文件(appliaction.views.layouts.column1.php)里面的$content。

  还有一个奇怪的问题,在application.views.layous.column1.php里面调用了这个方法:
  $this->beginContent(‘//layouts/main’);
  这是干什么用的呢,再看代码:发现这个方法是CController继承CBaseController的方法,函数原型如下:

public function beginContent($view=null,$data=array()){
    $this->beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data));
}

public function beginWidget($className,$properties=array()){
    $widget=$this->createWidget($className,$properties);
    //在这里我猜应该是创建了小物件的组,将它们给到控制器的_widgetStack[]里面,这样一来,不管是Layout文件还是模板文件里面如果需要使用小物件,就可以直接使用$this->widget()或者$this->beginWidget()这样的方法快速创建HTML了。
    $this->_widgetStack[]=$widget;
    return $widget;
}

public function createWidget($className,$properties=array()){
    $widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
    $widget->init();
    return $widget;
}

  另外还有一个问题,在views/layouts/下这两个文件column1.php 和 main.php

//column1.php
 $this->beginContent('//layouts/main'); ?>
<div id="content">
     echo $content; ?>
div>
 $this->endContent(); ?>

  在这个文件,它使用layouts/main.php来覆盖,beginContent(‘//layouts/main’) 表示以 main 为布局,在 beginContent() 和 endContent() 之间为 content 呈现的修改。
  所以说yii在 $this->render(‘index’) 一个页面的时候,使用 column1.php 包含 main.php,再由 main.php 包含 index.php,最后返回内容.
  所以说,在column1.php里面的$content,是用main.php的内容来替换;在main.php里面的$content,是用views/site/index.php来替换。

你可能感兴趣的:(web开发)