YII 的源码分析(二),yii源码分析
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 />

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

With the continuous development of cloud computing technology, data backup has become something that every enterprise must do. In this context, it is particularly important to develop a highly available cloud backup system. The PHP framework Yii is a powerful framework that can help developers quickly build high-performance web applications. The following will introduce how to use the Yii framework to develop a highly available cloud backup system. Designing the database model In the Yii framework, the database model is a very important part. Because the data backup system requires a lot of tables and relationships

As the demand for web applications continues to grow, developers have more and more choices in choosing development frameworks. Symfony and Yii2 are two popular PHP frameworks. They both have powerful functions and performance, but when faced with the need to develop large-scale web applications, which framework is more suitable? Next we will conduct a comparative analysis of Symphony and Yii2 to help you make a better choice. Basic Overview Symphony is an open source web application framework written in PHP and is built on

As the Internet continues to develop, the demand for web application development is also getting higher and higher. For developers, developing applications requires a stable, efficient, and powerful framework, which can improve development efficiency. Yii is a leading high-performance PHP framework that provides rich features and good performance. Yii3 is the next generation version of the Yii framework, which further optimizes performance and code quality based on Yii2. In this article, we will introduce how to use Yii3 framework to develop PHP applications.

In the current information age, big data, artificial intelligence, cloud computing and other technologies have become the focus of major enterprises. Among these technologies, graphics card rendering technology, as a high-performance graphics processing technology, has received more and more attention. Graphics card rendering technology is widely used in game development, film and television special effects, engineering modeling and other fields. For developers, choosing a framework that suits their projects is a very important decision. Among current languages, PHP is a very dynamic language. Some excellent PHP frameworks such as Yii2, Ph

The Yii framework is an open source PHP Web application framework that provides numerous tools and components to simplify the process of Web application development, of which data query is one of the important components. In the Yii framework, we can use SQL-like syntax to access the database to query and manipulate data efficiently. The query builder of the Yii framework mainly includes the following types: ActiveRecord query, QueryBuilder query, command query and original SQL query

If you're asking "What is Yii?" check out my previous tutorial: Introduction to the Yii Framework, which reviews the benefits of Yii and outlines what's new in Yii 2.0, released in October 2014. Hmm> In this Programming with Yii2 series, I will guide readers in using the Yii2PHP framework. In today's tutorial, I will share with you how to leverage Yii's console functionality to run cron jobs. In the past, I've used wget - a web-accessible URL - in a cron job to run my background tasks. This raises security concerns and has some performance issues. While I discussed some ways to mitigate the risk in our Security for Startup series, I had hoped to transition to console-driven commands

With the rapid development of the Internet, APIs have become an important way to exchange data between various applications. Therefore, it has become increasingly important to develop an API framework that is easy to maintain, efficient, and stable. When choosing an API framework, Yii2 and Symfony are two popular choices among developers. So, which one is more suitable for API development? This article will compare these two frameworks and give some conclusions. 1. Basic introduction Yii2 and Symfony are mature PHP frameworks with corresponding extensions that can be used to develop

Yii framework: This article introduces Yii's method of converting objects into arrays or directly outputting them into json format. It has certain reference value and I hope it can help you.
