目錄
YII 的源码分析(二),yii源码分析
首頁 php教程 php手册 YII 的源码分析(二),yii源码分析

YII 的源码分析(二),yii源码分析

Jun 13, 2016 am 09:19 AM
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 />
登入後複製
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用PHP框架Yii開發一個高可用的雲端備份系統 如何使用PHP框架Yii開發一個高可用的雲端備份系統 Jun 27, 2023 am 09:04 AM

隨著雲端運算技術的不斷發展,資料的備份已經成為了每個企業必須要做的事情。在這樣的背景下,開發一款高可用的雲端備份系統尤其重要。而PHP框架Yii是一款功能強大的框架,可以幫助開發者快速建立高效能的Web應用程式。以下將介紹如何使用Yii框架開發一款高可用的雲端備份系統。設計資料庫模型在Yii框架中,資料庫模型是非常重要的一環。因為資料備份系統需要用到很多的表和關

php如何使用Yii3框架? php如何使用Yii3框架? May 31, 2023 pm 10:42 PM

隨著互聯網的不斷發展,Web應用程式開發的需求也越來越高。對於開發人員而言,開發應用程式需要一個穩定、高效、強大的框架,這樣可以提高開發效率。 Yii是一款領先的高效能PHP框架,它提供了豐富的特性和良好的性能。 Yii3是Yii框架的下一代版本,它在Yii2的基礎上進一步優化了效能和程式碼品質。在這篇文章中,我們將介紹如何使用Yii3框架來開發PHP應用程式。

Symfony vs Yii2:哪個框架比較適合開發大型Web應用? Symfony vs Yii2:哪個框架比較適合開發大型Web應用? Jun 19, 2023 am 10:57 AM

隨著Web應用需求的不斷增長,開發者在選擇開發框架方面也越來越有選擇的空間。 Symfony和Yii2是兩個備受歡迎的PHP框架,它們都具有強大的功能和效能,但在面對需要開發大型網路應用程式時,哪個框架更適合呢?接下來我們將對Symphony和Yii2進行比較分析,以幫助你更好地進行選擇。基本概述Symphony是一個由PHP編寫的開源Web應用框架,它是建立

Yii框架中的資料查詢:有效率地存取數據 Yii框架中的資料查詢:有效率地存取數據 Jun 21, 2023 am 11:22 AM

Yii框架是一個開源的PHPWeb應用程式框架,提供了眾多的工具和元件,簡化了Web應用程式開發的流程,其中資料查詢是其中一個重要的元件之一。在Yii框架中,我們可以使用類似SQL的語法來存取資料庫,從而有效率地查詢和操作資料。 Yii框架的查詢建構器主要包括以下幾種類型:ActiveRecord查詢、QueryBuilder查詢、命令查詢和原始SQL查詢

Yii2 vs Phalcon:哪個框架更適合開發顯示卡渲染應用? Yii2 vs Phalcon:哪個框架更適合開發顯示卡渲染應用? Jun 19, 2023 am 08:09 AM

在當前資訊時代,大數據、人工智慧、雲端運算等技術已成為了各大企業關注的熱點。在這些技術中,顯示卡渲染技術作為一種高效能圖形處理技術,受到了越來越多的關注。顯示卡渲染技術廣泛應用於遊戲開發、影視特效、工程建模等領域。而對於開發者來說,選擇一個適合自己專案的框架,是一個非常重要的決策。在目前的語言中,PHP是一種相當有活力的語言,一些優秀的PHP框架如Yii2、Ph

Yii2程式設計指南:執行Cron服務的方法 Yii2程式設計指南:執行Cron服務的方法 Sep 01, 2023 pm 11:21 PM

如果您問「Yii是什麼?」請參閱我之前的教學:Yii框架簡介,其中回顧了Yii的優點,並概述了2014年10月發布的Yii2.0的新增功能。嗯>在這個使用Yii2程式設計系列中,我將指導讀者使用Yii2PHP框架。在今天的教學中,我將與您分享如何利用Yii的控制台功能來執行cron作業。過去,我在cron作業中使用了wget—可透過Web存取的URL來執行我的後台任務。這引發了安全性問題並存在一些效能問題。雖然我在我們的啟動系列安全性專題中討論了一些減輕風險的方法,但我曾希望過渡到控制台驅動的命令

Yii2 vs Symfony:哪個框架比較適合API開發? Yii2 vs Symfony:哪個框架比較適合API開發? Jun 18, 2023 pm 11:00 PM

隨著網路的快速發展,API成為了各種應用間資料交換的重要方式。因此,開發一款易於維護、高效、穩定的API框架變得越來越重要。而在選擇API框架時,Yii2和Symfony是兩個備受開發者歡迎的選擇。那麼,哪一個比較適合API開發呢?本文將對這兩個框架進行比較,並給出一些結論。一、基本介紹Yii2和Symfony都是成熟的PHP框架,都有相應的擴展,可以用來開

yii如何將物件轉換為陣列或直接輸出為json格式 yii如何將物件轉換為陣列或直接輸出為json格式 Jan 08, 2021 am 10:13 AM

yii框架:本文為大家介紹了yii將物件轉換為陣列或直接輸出為json格式的方法,具有一定的參考價值,希望能幫助大家。

See all articles