YII 的源码分析(二),yii源码分析
上一篇简单分析了一下yii的流程,从创建一个应用,到屏幕上输出结果。这一次我来一个稍复杂一点的,重点在输出上,不再是简单的一行"hello world",而是要经过view(视图)层的处理。
依然是demos目录,这次我们选择hangman,一个简单的猜字游戏。老规则,还是从入口处开始看。
index.php:
<?<span>php </span><span>//</span><span> change the following paths if necessary</span> <span>$yii</span>=<span>dirname</span>(<span>__FILE__</span>).'/../../framework/yii.php'<span>; </span><span>$config</span>=<span>dirname</span>(<span>__FILE__</span>).'/protected/config/main.php'<span>; </span><span>//</span><span> remove the following line when in production mode // defined('YII_DEBUG') or define('YII_DEBUG',true);</span> <span>require_once</span>(<span>$yii</span><span>); Yii</span>::createWebApplication(<span>$config</span>)->run();
和helloworld应用相比,这次多了main.php,打开main看下源码:
<?<span>php </span><span>return</span> <span>array</span><span>( </span>'name'=>'Hangman Game', 'defaultController'=>'game', 'components'=><span>array</span><span>( </span>'urlManager'=><span>array</span><span>( </span>'urlFormat'=>'path', 'rules'=><span>array</span><span>( </span>'game/guess/<g:\w>'=>'game/guess',<span> )</span>,<span> )</span>,<span> )</span>,<span> );</span>
在我们以后的实际项目中,也是经常要用到配置文件的,所以我觉得有必要了解一下yii的配置文件--main.php
'name'=>'这里通常是定义网站的标题',也就是我们打开index.php时,在网页上显示的标题。
'defaultController'=>'这里是默认的控制器',也就是我们的index.php后面没有指定控制器时系统采用的控制器,如果我们这里没有指出来,默认就是site
'components'=>'这里是组件的参数,用多维数组进行配置。' 具体的参数可以查看yii手册。
Yii::createWebApplication($config)->run(); 上一次我们已经详细分析过它了,这里再简单的走一遍:
CWebApplication.php -> CApplication.php -> __construct($config) :
<span>$this</span>-><span>preinit(); </span><span>$this</span>-><span>initSystemHandlers(); </span><span>$this</span>-><span>registerCoreComponents(); </span><span>$this</span>->configure(<span>$config</span><span>); </span><span>$this</span>->attachBehaviors(<span>$this</span>-><span>behaviors); </span><span>$this</span>-><span>preloadComponents(); </span><span>$this</span>->init();
上次我们没有配置过程,所以$this->configure($config)什么也没有做,但是这次有配置参数,所以我们进去看看yii做了哪些操作:
CApplication自己没有实现configure方法,是继承于CModule.php的:
<span>public</span> <span>function</span> configure(<span>$config</span><span>) { </span><span>if</span>(<span>is_array</span>(<span>$config</span><span>)) { </span><span>foreach</span>(<span>$config</span> <span>as</span> <span>$key</span>=><span>$value</span><span>) </span><span>$this</span>-><span>$key</span>=<span>$value</span><span>; } }</span>
代码非常简单,就是把配置参数的键做为类的属性名,value做为类的属性值进行了扩展。完成这一过程就运行CApplication 上的run方法了。
<span>public</span> <span>function</span><span> run() { </span><span>if</span>(<span>$this</span>->hasEventHandler('onBeginRequest'<span>)) </span><span>$this</span>->onBeginRequest(<span>new</span> CEvent(<span>$this</span><span>)); </span><span>register_shutdown_function</span>(<span>array</span>(<span>$this</span>,'end'),0,<span>false</span><span>); </span><span>$this</span>-><span>processRequest(); </span><span>if</span>(<span>$this</span>->hasEventHandler('onEndRequest'<span>)) </span><span>$this</span>->onEndRequest(<span>new</span> CEvent(<span>$this</span><span>)); }</span>
我们前面说过,这里只要关注 $this->processRequest(); 就可以了。运行的结果就是执行$this->runController('');
<span>public</span> <span>function</span> runController(<span>$route</span><span>) { </span><span>if</span>((<span>$ca</span>=<span>$this</span>->createController(<span>$route</span>))!==<span>null</span><span>) { </span><span>list</span>(<span>$controller</span>,<span>$actionID</span>)=<span>$ca</span><span>; </span><span>$oldController</span>=<span>$this</span>-><span>_controller; </span><span>$this</span>->_controller=<span>$controller</span><span>; </span><span>$controller</span>-><span>init(); </span><span>$controller</span>->run(<span>$actionID</span><span>); </span><span>$this</span>->_controller=<span>$oldController</span><span>; } </span><span>else</span> <span>throw</span> <span>new</span> CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".', <span>array</span>('{route}'=><span>$route</span>===''?<span>$this</span>->defaultController:<span>$route</span><span>))); }</span>
由于url是index.php,后面没有任何参数,所以都是走的默认控制器,也就是我们在main.php中设定的game. 所以$controller 就等于 controllers/gameController.php, 通过上次的源码分析我们可以知道,在gameController.php中没有init方法时,都是走的父类中定义的默认方法(实际上是一个空方法),
$controller->run($actionID<span>); == gameController</span>->run(''); gameController上没有实现run方法,于是又是去父类中找run
从class GameController extends CController 可以看出,父类是CController , 找到相应的run方法:
<span>public</span> <span>function</span> run(<span>$actionID</span><span>) { </span><span>if</span>((<span>$action</span>=<span>$this</span>->createAction(<span>$actionID</span>))!==<span>null</span><span>) { </span><span>if</span>((<span>$parent</span>=<span>$this</span>->getModule())===<span>null</span><span>) </span><span>$parent</span>=Yii::<span>app(); </span><span>if</span>(<span>$parent</span>->beforeControllerAction(<span>$this</span>,<span>$action</span><span>)) { </span><span>$this</span>->runActionWithFilters(<span>$action</span>,<span>$this</span>-><span>filters()); </span><span>$parent</span>->afterControllerAction(<span>$this</span>,<span>$action</span><span>); } } </span><span>else</span> <span>$this</span>->missingAction(<span>$actionID</span><span>); }</span>
前面已经分析过了,没有指定时,都是默认参数。那么此时的$actionID为空,actionID就是gameController中定义的默认动作:public $defaultAction='play';
runActionWithFilters ---> runAction --> $action->runWithParams<br /><br />这里的$action 需要从CAction -> CInlineAction中去找<br /><br />
<span>public</span> <span>function</span> runWithParams(<span>$params</span><span>) { </span><span>$methodName</span>='action'.<span>$this</span>-><span>getId(); </span><span>$controller</span>=<span>$this</span>-><span>getController(); </span><span>$method</span>=<span>new</span> ReflectionMethod(<span>$controller</span>, <span>$methodName</span><span>); </span><span>if</span>(<span>$method</span>->getNumberOfParameters()>0<span>) </span><span>return</span> <span>$this</span>->runWithParamsInternal(<span>$controller</span>, <span>$method</span>, <span>$params</span><span>); </span><span>else</span> <span>return</span> <span>$controller</span>-><span>$methodName</span><span>(); }</span>
走了这么多过程,和hello world的流程是差不多的。据上次的分析可以知道,这里执行了
$controller->$methodName<span>(); 也就是GameController->actionPlay()<br /><br />到此,我们本节的重点才真正开始:<br /></span>
<span>public</span> <span>function</span><span> actionPlay() { </span><span>static</span> <span>$levels</span>=<span>array</span><span>( </span>'10'=>'Easy game; you are allowed 10 misses.', '5'=>'Medium game; you are allowed 5 misses.', '3'=>'Hard game; you are allowed 3 misses.',<span> ); </span><span>//</span><span> if a difficulty level is correctly chosen</span> <span>if</span>(<span>isset</span>(<span>$_POST</span>['level']) && <span>isset</span>(<span>$levels</span>[<span>$_POST</span>['level'<span>]])) { </span><span>$this</span>->word=<span>$this</span>-><span>generateWord(); </span><span>$this</span>->guessWord=<span>str_repeat</span>('_',<span>strlen</span>(<span>$this</span>-><span>word)); </span><span>$this</span>->level=<span>$_POST</span>['level'<span>]; </span><span>$this</span>->misses=0<span>; </span><span>$this</span>->setPageState('guessed',<span>null</span><span>); </span><span>//</span><span> show the guess page</span> <span>$this</span>->render('guess'<span>); } </span><span>else</span><span> { </span><span>$params</span>=<span>array</span><span>( </span>'levels'=><span>$levels</span>, <span>//</span><span> if this is a POST request, it means the level is not chosen</span> 'error'=>Yii::app()->request->isPostRequest,<span> ); </span><span>//</span><span> show the difficulty level page</span> <span>$this</span>->render('play',<span>$params</span><span>); } }</span>
<span>显然走的是else的逻辑,重点请看</span> $this->render('play',$params); 这个render方法这么面熟,很多框架中都有类似的方法,比如discuz,smarty,CI 等等. 纵观yii框架,rnder 在它整个MVC模式中,是V得以实现的重要骨干。所以有必要把它翻个底朝天。<br />在CController.php中有这个方法:
<span>public</span> <span>function</span> render(<span>$view</span>,<span>$data</span>=<span>null</span>,<span>$return</span>=<span>false</span><span>) { </span><span>if</span>(<span>$this</span>->beforeRender(<span>$view</span><span>)) { </span><span>$output</span>=<span>$this</span>->renderPartial(<span>$view</span>,<span>$data</span>,<span>true</span><span>); </span><span>if</span>((<span>$layoutFile</span>=<span>$this</span>->getLayoutFile(<span>$this</span>->layout))!==<span>false</span><span>) </span><span>$output</span>=<span>$this</span>->renderFile(<span>$layoutFile</span>,<span>array</span>('content'=><span>$output</span>),<span>true</span><span>); </span><span>$this</span>->afterRender(<span>$view</span>,<span>$output</span><span>); </span><span>$output</span>=<span>$this</span>->processOutput(<span>$output</span><span>); </span><span>if</span>(<span>$return</span><span>) </span><span>return</span> <span>$output</span><span>; </span><span>else</span> <span>echo</span> <span>$output</span><span>; } }</span>
当我们echo $output=$this->renderPartial($view,$data,true);的时候,就发现,此时的$output已经就拿到我们最终的结果了。它对应的文件是views/game/play.php
也就是我们在index.php上最终看到的内容了。由于本次渲染比较简单,所以程序经过的流程也较少,但是从源码中可以看到,里边进行了许多的处理,比如主题什么的。本次就先分析到这。晚安!
<br /><br /><br />

随着互联网的不断发展,Web应用程序开发的需求也越来越高。对于开发人员而言,开发应用程序需要一个稳定、高效、强大的框架,这样可以提高开发效率。Yii是一款领先的高性能PHP框架,它提供了丰富的特性和良好的性能。Yii3是Yii框架的下一代版本,它在Yii2的基础上进一步优化了性能和代码质量。在这篇文章中,我们将介绍如何使用Yii3框架来开发PHP应用程序。

随着云计算技术的不断发展,数据的备份已经成为了每个企业必须要做的事情。在这样的背景下,开发一款高可用的云备份系统尤为重要。而PHP框架Yii是一款功能强大的框架,可以帮助开发者快速构建高性能的Web应用程序。下面将介绍如何使用Yii框架开发一款高可用的云备份系统。设计数据库模型在Yii框架中,数据库模型是非常重要的一部分。因为数据备份系统需要用到很多的表和关

在当前信息时代,大数据、人工智能、云计算等技术已经成为了各大企业关注的热点。在这些技术中,显卡渲染技术作为一种高性能图形处理技术,受到了越来越多的关注。显卡渲染技术被广泛应用于游戏开发、影视特效、工程建模等领域。而对于开发者来说,选择一个适合自己项目的框架,是一个非常重要的决策。在当前的语言中,PHP是一种颇具活力的语言,一些优秀的PHP框架如Yii2、Ph

随着Web应用需求的不断增长,开发者们在选择开发框架方面也越来越有选择的余地。Symfony和Yii2是两个备受欢迎的PHP框架,它们都具有强大的功能和性能,但在面对需要开发大型Web应用时,哪个框架更适合呢?接下来我们将对Symphony和Yii2进行比较分析,以帮助你更好地进行选择。基本概述Symphony是一个由PHP编写的开源Web应用框架,它是建立

Yii框架是一个开源的PHPWeb应用程序框架,提供了众多的工具和组件,简化了Web应用程序开发的流程,其中数据查询是其中一个重要的组件之一。在Yii框架中,我们可以使用类似SQL的语法来访问数据库,从而高效地查询和操作数据。Yii框架的查询构建器主要包括以下几种类型:ActiveRecord查询、QueryBuilder查询、命令查询和原始SQL查询

yii框架:本文为大家介绍了yii将对象转化为数组或直接输出为json格式的方法,具有一定的参考价值,希望能够帮助到大家。

如果您问“Yii是什么?”查看我之前的教程:Yii框架简介,其中回顾了Yii的优点,并概述了2014年10月发布的Yii2.0的新增功能。嗯>在这个使用Yii2编程系列中,我将指导读者使用Yii2PHP框架。在今天的教程中,我将与您分享如何利用Yii的控制台功能来运行cron作业。过去,我在cron作业中使用了wget—可通过Web访问的URL来运行我的后台任务。这引发了安全问题并存在一些性能问题。虽然我在我们的启动系列安全性专题中讨论了一些减轻风险的方法,但我曾希望过渡到控制台驱动的命令

随着互联网的快速发展,Web应用越来越成为人们生活中不可或缺的一部分。而表单是Web应用中不可或缺的元素之一,其用于收集用户数据,让Web应用能够更好地为用户服务。Yii框架是一个快速、高效、灵活的PHP框架,可以帮助开发人员更加快速地开发Web应用。Yii框架中的表单构建器(FormBuilder)可以让开发人员轻松地构建复杂的表单,让Web应用具有更好


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

드림위버 CS6
시각적 웹 개발 도구

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기
