`

Yii分析9:CController控制视图(Cview)的展现

 
阅读更多

 

    《The Definitive Guide to Yii》描述了视图的概念:“视图是一个包含了主要的用户交互元素的PHP脚本.他可以包含PHP语句”,不同于很多类似的框架,Yii并没有使用smarty作为模板引擎,而是直接使用原生的PHP脚本作为模板,笔者认为至少有以下两点好处:

  (1) 门槛低,易于使用,不需要理解和记忆smarty的模板语言语法

  (2) 减少了模板引擎解析的过程,直接include,结合opcode缓存,效率可能会更高

当然也有缺点:

  (1) 没有smarty的前端过滤功能,前后端分离开发也有一定的门槛(前端工程师需要学习PHP语法,尤其是字符串处理相关函数)

  (2) 直接使用PHP,对于一些约束很难控制,比如全局的错误级别,如何控制逻辑处理与数据处理的界限?

      因此,对于是使用PHP原生脚本还是使用smarty作为模板各有利弊,不论程序开发人员使用哪一种,都要了解这种方式的利弊才能更加安全有效地进行开发。

 

在Yii中,显示一个视图非常简单,即调用Ccontroller的方法render:

 

$this->render(‘viewName’);

 

 而这个过程是如何实现的呢?我们看看render这个方法的源码:

 

/**
	 * 使用框架来渲染一个视图
	 *
	 * 这个方法首先调用{@link renderPartial}来渲染视图 (内容视图)
	 * 然后渲染框架视图(在合适的位置嵌入内容视图)
	 * 在框架视图中,内容视图的渲染结果以变量的方式来访问
	 * 最后,调用{@link processOutput}在可用时来插入脚本
	 * 和动态内容
	 *
	 * 默认的框架视图位置为:"protected/views/layouts/main.php".
	 * 可以通过设置{@link layout}.来自定义
	 *
	 * @param string $view 要被渲染的视图名称See {@link getViewFile} for details
	 * about how the view script is resolved.
	 * @param array $data 在视图中被解析为PHP变量的数据
	 * @param boolean $return 返回渲染的结果或者直接显示给最终用户
	 * @return string the rendering result. Null if the rendering result is not required.
	 * @see renderPartial
	 * @see getLayoutFile
	 */
	public function render($view,$data=null,$return=false)
	{
		//触发beforeRender事件,beforeRender直接返回true(子类覆盖自定义)
		if($this->beforeRender($view))
		{
			//将$view的内容渲染后返回给变量$output
			$output=$this->renderPartial($view,$data,true);
			if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
				//将$output作为数据渲染整个框架
				$output=$this->renderFile($layoutFile,array('content'=>$output),true);
			//afterRender是一个空函数,子类覆盖自定义
			$this->afterRender($view,$output);
			
			//处理输出
			$output=$this->processOutput($output);

			//返回or直接输出
			if($return)
				return $output;
			else
				echo $output;
		}
	}

 

 

      在render的过程中,用到了另外render函数:renderPartial和renderFile,renderPartial是CController的一个成员函数:

 

 

/**
	 * 渲染一个视图
	 *
	 * 视图名,指向一个PHP脚本通过{@link getViewFile}解析
	 * 如果$data是一个数组,会被解析为PHP的变量
	 * 可以在视图脚本中使用
	 *
	 * 这个方法不同于{@link render(),他不会使用框架(layout)来渲染
	 * 常用来渲染一个视图的一部分,或者AJAX响应
	 *
	 * @param string $view 被渲染的视图名称{@link getViewFile}
	 * @param array $data 被解析为PHP变量的数据,在视图脚本中可用
	 * @param boolean $return 渲染的结果是否被返回,否则直接展示给最终用户
	 * @param boolean $processOutput 是否使用{@link processOutput}来处理渲染结果
	 * @return string 渲染结果
	 * @throws CException 如果视图不存在会抛出异常
	 * @see getViewFile
	 * @see processOutput
	 * @see render
	 */
	public function renderPartial($view,$data=null,$return=false,$processOutput=false)
	{
		//获取视图路径
		if(($viewFile=$this->getViewFile($view))!==false)
		{
			//调用renderFile来返回渲染结果
			$output=$this->renderFile($viewFile,$data,true);
			if($processOutput)
				$output=$this->processOutput($output);
			//返回or直接显示
			if($return)
				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)));
	}

 

 renderFile并不是在CController中定义的,而是在CController的父类CBaseController中定义:

       /**
	 * 渲染一个视图文件
	 *
	 * @param string $viewFile 视图文件路径view file path
	 * @param array $data 解析为变量的数据
	 * @param boolean $return 是否返回渲染结果
	 * @return string 渲染结果
	 * @throws CException if the view file does not exist
	 */
	public function renderFile($viewFile,$data=null,$return=false)
	{
		$widgetCount=count($this->_widgetStack);
		//获取renderer类,同时检查视图文件扩展名,默认情况下,是没有自定义的viewRenderer对象的,Yii内置了抽象类CViewRenderer,如果自定义可以继承这个类
		if(($renderer=Yii::app()->getViewRenderer())!==null && $renderer->fileExtension==='.'.CFileHelper::getExtension($viewFile))
			//如果renderer的扩展名与视图文件扩展名相同
			$content=$renderer->renderFile($this,$viewFile,$data,$return);
		else
			//调用renderInternal
			$content=$this->renderInternal($viewFile,$data,$return);
		//使用widget的堆栈计数,如果与widgetCount不一致,说明没有调用endWidget()来释放
		if(count($this->_widgetStack)===$widgetCount)
			return $content;
		else
		{
			$widget=end($this->_widgetStack);
			throw new CException(Yii::t('yii','{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.',
				array('{controller}'=>get_class($this), '{view}'=>$viewFile, '{widget}'=>get_class($widget))));
		}
	}

 renderInternal代码如下:

        public function renderInternal($_viewFile_,$_data_=null,$_return_=false)
	{
		// we use special variable names here to avoid conflict when extracting data
		if(is_array($_data_))
			//如果data是数组,使用extract
			extract($_data_,EXTR_PREFIX_SAME,'data');
		else
			//如果不是数组,直接赋给$data变量
			$data=$_data_;
		//如果需要返回,使用ob进行缓冲输出,之后再返回,否则直接调用require(如果文件不存在,会导致一个fatal error)
		if($_return_)
		{
			ob_start();
			ob_implicit_flush(false);
			require($_viewFile_);
			return ob_get_clean();
		}
		else
			require($_viewFile_);
	}

 接着,我们来看一下在渲染玩view文件之后,处理输出的过程:

 

        /**
	 *由{@link render()}调用处理最后的输出
	 * 这个方法在{@link render()}和{@link renderText()}的结尾调用
	 * 如果有注册的客户端脚本,这个方法会把他们在合适的位置
	 * 插入到输出中。如果有动态内容,也会被插入
	 * 这个方法可能会在页面的隐藏状态窗口中保存页面的持久状态
	 * @param string $output 由当前action产生的输出
	 * @return string 处理过的输出
	 */
	public function processOutput($output)
	{
		//插入客户端脚本
		Yii::app()->getClientScript()->render($output);

		// 如果使用了页面缓存,我们可以延迟动态内容的替换
		if($this->_dynamicOutput!==null && $this->isCachingStackEmpty())
			$output=$this->processDynamicOutput($output);
		
		//页面状态的处理
		if($this->_pageStates===null)
			$this->_pageStates=$this->loadPageStates();
		if(!empty($this->_pageStates))
			$this->savePageStates($this->_pageStates,$output);

		return $output;
	}
	public function processDynamicOutput($output)
	{
		if($this->_dynamicOutput)
		{
			//使用正则替换特殊字符
				$output=preg_replace_callback('/<###dynamic-(\d+)###>/',array($this,'replaceDynamicOutput'),$output);
		}
		return $output;
	}
 

     至此,整个render过程已经完成,总结下来,主要经历了数据解析和require,加载客户端脚本和动态数据两部分。

 

3
1
分享到:
评论
2 楼 silentime 2011-12-13  
z.y.f 写道
先赞一个~感觉smarty本身在前后端开发分离上的作用不大,倒是可以防止出现view层出现过多的逻辑代码,可以规范一下view代码,使之只负责数据展示。。。

1 楼 z.y.f 2011-12-10  
先赞一个~感觉smarty本身在前后端开发分离上的作用不大,倒是可以防止出现view层出现过多的逻辑代码,可以规范一下view代码,使之只负责数据展示。。。

相关推荐

    Yii权威指南思维导图

    控制器(CController)是处理用户请求的中心,它包含了动作(Action)和过滤器(Filter)。过滤器可以在执行动作之前或之后运行,提供了权限检查、日志记录等功能。 此外,Yii提供了丰富的缓存机制,包括数据缓存...

    Yii+Framework+v1.1.10类参考中文手册(CHM版)

    3. **CController**: MVC中的控制器,负责接收用户请求,调用模型进行数据处理,并通过视图显示结果。 4. **CModel**: 数据模型,封装了业务逻辑和数据验证,是数据操作的核心。 5. **CActiveRecord**: 实现了...

    yii框架资源上出纳

    CController和CView则分别代表控制器和视图,实现了MVC设计模式;而CModel则用于数据处理和业务逻辑,与数据库交互通常通过 CActiveRecord 实现。 在升级到Yii 2.0后,框架进行了许多改进,如增强的性能、更强大的...

    yii-1.1.5.r2654.zip

    - **web**:Web应用程序相关的类,如CController、CView等。 - **widgets**:预定义的可重用的Web小部件,如CMenu、CLinkPager等。 2. **docs**:框架的官方文档,可能包括API参考、教程和用户指南,帮助开发者...

    li_3ck_02a_1118.pdf

    li_3ck_02a_1118

    基于MATLAB的牛顿迭代法实现

    基于MATLAB的牛顿迭代法实现

    mellitz_3ck_01_0319.pdf

    mellitz_3ck_01_0319

    2025探索银行业人工智能驱动技术转型的投资回报率

    内容概要:文章阐述了银行采用人工智能(AI)技术替代传统系统的紧迫性和收益,讨论了通过构建现代化的数据和技术平台实现效率提升的方法,同时强调实施过程中确保数据质量和建立信任的重要性。文中提及,在金融行业中,若想优化业绩则必须拥抱AI带来的机遇,并为此进行经营模式的革新。根据Workday主办的研讨会内容,PwC金融服务风险与监管领导和Workday金融服务高层指出了大部分银行对AI认知不足的问题,强调AI在金融、人力资源以及IT等领域的广泛应用潜力及具体应用场景,如欺诈检测、技能映射和财务管理方面的作用。并且提到了AI部署过程中可能出现的技术与非技术难题及相应解决办法,鼓励金融机构及时投资建设新型基础设施,以保持竞争力。 适用人群:银行及其他金融机构管理人员;金融科技领域的专业研究人员;对企业数字化和智能化转型感兴趣的商业分析师、投资者;从事信息技术咨询工作的顾问。 使用场景及目标:本文可以帮助金融机构制定合理的技术发展战略规划,评估是否有必要推进AI技术转型,同时也为希望涉足银行科技项目的开发者提供了宝贵的市场洞察,帮助理解行业内普遍存在的困难与潜在的市场需求。此外,对于想要了解银行

    matlab程序代码项目案例论文+程序 基于在线优化的快速模型预测控制Fast model predicitive control with matlab interface.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_043071]Phase Manager and a Scalable Batching Solution.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_044386]1769-SM2 Compact I-O to DSI Module - Multi Drive Mode Operation - with.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_041232]Monitor I-O Connections in Logix.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    chromedriver-linux64-136.0.7058.0.zip

    chromedriver-linux64-136.0.7058.0.zip

    [AB PLC例程源码][MMS_042504]Logix5000 interface to Atlas-Copco Tool Controller over EtherNet-IP.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_042349]How to read-write data to-from a PLC using OPC in Visual Basic 6.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    电力工程领域中背压热电联产电厂的设计与参数计算

    内容概要:本文档介绍了背压热电联产(CHP)发电厂的详细设计步骤,涵盖确定各状态点的压力、温度、比焓以及质量流率的具体方法。主要内容围绕计算净电功率、燃料消耗及其效率展开,并提供了T-s图绘制的指南。针对每个组件(如蒸汽轮机、冷凝器、除氧器等),都列出了详细的效率假设和压力损失表,为实际工程应用提供了宝贵的参考资料和操作指导。同时,该作业任务要求学生从给定初始值中选择合适的操作条件进行系统模拟,并利用课程讲义和Moodle平台资料完成计算流程。 适用人群:对能源转换和动力设备设计感兴趣的学生或者初涉该领域的工程师。 使用场景及目标:旨在帮助学员深入了解并掌握背压热电联产装置的工作原理和技术指标计算的方法论,通过实践练习提高他们的问题解决能力。 其他说明:文档强调了稳态运行假设的重要性,即物质平衡等于能量输入等于输出的原则,并鼓励参与者借助附录提供的典型操作参数图表来寻找解决问题的方向。此外,它还特别指出对于一些变量值求解可能需要迭代法来进行调整,直至获得稳定结果。提交的报告必须含有一份详细的T-s图和其他必要附件。

    机器学习-市财政收入分析(含数据集)

    机器学习_市财政收入分析(含数据集)

    [AB PLC例程源码][MMS_046989]KAT with Code Sequencer.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    tracy_3cd_01_0318.pdf

    tracy_3cd_01_0318

    lusted_3cd_01_0918.pdf

    lusted_3cd_01_0918

Global site tag (gtag.js) - Google Analytics