YIIのソースコード解析(-)

WBOY
リリース: 2016-08-08 09:33:00
オリジナル
1205 人が閲覧しました

最初のソース コード分析として、私は yii (ワイアイアイではなくワイアイイーと発音します) を選択しました。その称賛についてはこれ以上は言わず、本題に入ります。まず材料を準備します。公式 Web サイトから yii ソースコード パッケージの最新バージョン (1.1.15) を直接ダウンロードすることをお勧めします。

デモには最も単純なアプリケーションの 1 つである helloworld があり、これは yii フレームワークを使用して「hello world」;

という文を出力します。

そこから始めて、フレームワークが最小限のプロセスを実行するために経由するコンポーネントを分析し、その動作プロセスを簡単に分析します。

単一エントリのドキュメントから読み始めてください。 (ソースコードは通常、呼び出し点から解析されます)

Index.php->

//Yii ブートストラップ ファイルをインクルードします

//スタートアップファイルを紹介します

require_once(dirname(__FILE__).'/../../framework/yii.php');

yii.php ->

//YiiBase は、一般的なフレームワーク機能を提供するヘルパー クラスです。

//YiiBase はフレームワーク全体を提供するヘルパー クラスです。多くの重要な定数がここで定義されています

require(dirname(__FILE__).'/YiiBase.php');

//自動読み込みクラスを登録する

spl_autoload_register(array('YiiBase','autoload'));

//インターフェイスクラスをインポートします

require(YII_PATH.'/base/interfaces.php');

//アプリケーションを起動します

Yii::createWebApplication()->run();

コードはここで終わっているようで、ページのコンテンツも表示されますが、フレームワークが何をしているのかはわかりません。したがって、このステップを分解して内部の詳細を明らかにする必要があります。

Yii::createWebApplication()->run()は3つの部分に分けることができます

  1. いい
  2. Webアプリケーションを作成する
  3. 走る

Yiiこれは何ですか?

このコード行は yii.php class Yii extends YiiBase から見つけることができます

これは YiiBase の継承クラスであることを意味し、作成者の拡張子は空白のままなので、Yii は単なる YiiBase への参照です。したがって、静的メソッド createWebApplication も YiiBase に存在する必要があります。

YiiBase.php では、次のメソッドを簡単に見つけることができます:

パブリック静的関数 createWebApplication($config=null)

return self::createApplication('CWebApplication',$config);

}

createApplication のタスクを再度渡します:

public static function createApplication($class,$config=null)

新しい $class($config) を返します。

}

組み合わせると、createWebApplication() は return new CWebApplication($config);

この CWebApplication クラスはどこですか?どのように導入されましたか?

一連の質問を抱えて、YiiBase.php に戻りました

そこでは非常に長い配列が定義されており、次のものが見つかります:

'CWebApplication' => '/web/CWebApplication.php'、これは自動読み込みクラスのメンバーです

自動ロードの実装方法については、spl_autoload_register の関連ドキュメントを参照できますが、ここでは無関係な詳細を説明します。

CWebApplication についてさらに詳しく見ていきましょう。ファイル /web/CWebApplication.php を開きます。

前述したように、私の経験によれば、newを使用する場合、通常はコンストラクターがありますが、そのコンストラクターが親クラスにあるはずなので、上位を検索してみました。 found class CWebApplication extends CApplication. 手がかりを追って少しずつ見つけていく必要がありました。

CApplication には確かにコンストラクターがあり、コードは次のとおりです:

リーリー

//上記は初期化、クラス参照、エイリアス、パスなどの設定とみなすことができます。

-$ This- & gt; // 当面は使用されず、将来の拡張に備えて残されると思われる

通り

通り

以来

以来

}

$this の下にある一部のメソッドは、親クラスから取得されている可能性があるため、現在のクラスでは見つかりません。見つからない場合は、クラスの宣言に移動して確認してください。

抽象クラス CApplication は CModule を拡張します

明らかに、CModule に入る必要がありますが、この時点でまだ必要なメソッドが見つからない場合は、前のプロセスに進みます:

抽象クラスCModuleはCComponentを拡張します

クラスCComponentまで

つまり、ここが彼らの現在の本拠地だということです。コード内のコメントからも確認できます:

CComponent はすべてのコンポーネントの基本クラスです

それは私の考えが正しいことを示しています、はい、それが基本クラスです。

コードを通して、現在のアプリケーションでは多くのパラメーターが空であるため、多くのロジックが直接スキップされていることがわかります。

これを見れば$thisの内容は大体わかります。もう一度振り返ってみましょう

return new CWebApplication($config)->run();

以前のレイヤーごとの分析により、この時点での実行方法も簡単に見つけることができます。 CApplication のすぐ内側:

リーリー

 

重点放在:$this->processRequest(); 因为前面和后面部分都是注册事件相关的,当前条件下执行不到。

<spanmicrosoft yahei font-size:><span>abstract</span> <span>public</span> <span>function</span> processRequest(); 这个方法在当前类中是抽象的,所以肯定在它的子类中实现了。回去找CWebApplication:

         <span>public</span> <span>function</span><span> processRequest()

         {

                   </span><span>if</span>(<span>is_array</span>(<span>$this</span>->catchAllRequest) && <span>isset</span>(<span>$this</span>->catchAllRequest[0<span>]))

                   {

                            </span><span>$route</span>=<span>$this</span>->catchAllRequest[0<span>];

                            </span><span>foreach</span>(<span>array_splice</span>(<span>$this</span>->catchAllRequest,1) <span>as</span> <span>$name</span>=><span>$value</span><span>)

                                     </span><span>$_GET</span>[<span>$name</span>]=<span>$value</span><span>;

                   }

                   </span><span>else</span>

                            <span>$route</span>=<span>$this</span>->getUrlManager()->parseUrl(<span>$this</span>-><span>getRequest());

 

                   </span><span>$this</span>->runController(<span>$route</span><span>);

         }</span></spanmicrosoft>
ログイン後にコピー

 

 

注意重点在$this->runController($route);

 

<spanmicrosoft yahei font-size:><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></spanmicrosoft>
ログイン後にコピー

 

 

我们要注意的代码只有两行:

$controller->init();

$controller->run($actionID);

这里的$controller可以能过查看createController得知,就是默认的控制器Sitecontroller.php

而Action则是index,你问我是怎么看出来的?哈哈,我在猜不出来的地方echo或var_dump一下不就可以了吗?这么简单的逻辑,还轮不到xdebug 这样的神器出场。

显然,init什么也没有做,看看run做了什么

Sitecontroller中没有run方法,又要去它的父类中查找。

class SiteController extends CController

 

在CController中有这个方法:

<spanmicrosoft yahei font-size:><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></spanmicrosoft>
ログイン後にコピー

 

能过查看$this->createAction($actionID),得到return new CInlineAction($this,$actionID);

我们呆会再看这个CInlineAction,先看$this->runActionWithFilters($action,$this->filters());

<spanmicrosoft yahei font-size:><span>public</span> <span>function</span> runActionWithFilters(<span>$action</span>,<span>$filters</span><span>)

         {

                   </span><span>if</span>(<span>empty</span>(<span>$filters</span><span>)){

                            </span><span>$this</span>->runAction(<span>$action</span><span>);

                   }

                   </span><span>else</span><span>

                   {

                            </span><span>$priorAction</span>=<span>$this</span>-><span>_action;

                            </span><span>$this</span>->_action=<span>$action</span><span>;

                            CFilterChain</span>::create(<span>$this</span>,<span>$action</span>,<span>$filters</span>)-><span>run();

                            </span><span>$this</span>->_action=<span>$priorAction</span><span>;

                   }

         }</span></spanmicrosoft>
ログイン後にコピー

 

显然$filters是空的,所以执行第一个表达式$this->runAction($action);

 

<spanmicrosoft yahei font-size:><span>public</span> <span>function</span> runAction(<span>$action</span><span>)

         {

 

                   </span><span>$priorAction</span>=<span>$this</span>-><span>_action;

                   </span><span>$this</span>->_action=<span>$action</span><span>;

                   </span><span>if</span>(<span>$this</span>->beforeAction(<span>$action</span><span>))

                   {

 

                            </span><span>if</span>(<span>$action</span>->runWithParams(<span>$this</span>->getActionParams())===<span>false</span><span>){

                                     </span><span>$this</span>->invalidActionParams(<span>$action</span><span>);

                            }

 

                            </span><span>else</span><span>{

                                     </span><span>$this</span>->afterAction(<span>$action</span><span>);

 

                            }

 

                   }

                   </span><span>$this</span>->_action=<span>$priorAction</span><span>;

         }</span></spanmicrosoft>
ログイン後にコピー

 

 

这段代码的重点是 $action->runWithParams($this->getActionParams())这一句;

这里的$action就是$this->createAction($actionID)返回的结果,而它的结果就是

return new CInlineAction($this,$actionID);

 

CInlineAction.php

是时候查看CInlineAction了;

 

        

<spanmicrosoft yahei font-size:> <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></spanmicrosoft>
ログイン後にコピー

 

哇哦,好高级,居然还用了反射,不过我喜欢!

不过呢,打印$method发现:

object(ReflectionMethod)#6 (2) {

 

["name"]=>

 

string(11) "actionIndex"

 

["class"]=>

 

string(14) "SiteController"

 

}

没有参数,所以此处代码相当于是执行了SiteController->actionIndex();

在class SiteController extends CController中可以看到actionIndex 的定义

        

<spanmicrosoft yahei font-size:> <span>public</span> <span>function</span><span> actionIndex()

         {

                   </span><span>echo</span> 'Hello World'<span>;

         }</span></spanmicrosoft>
ログイン後にコピー

 

于是就看到屏幕上那一句Hello World ,整个程序也就跑完了。也许有人要问了,为什么输出一句话还这么复杂,不是脱了裤子打屁吗? (请允许我的粗俗);

如果是这么简单的需求,当然不可能这么干。举这个例子,只是说明yii的基础流程,为下面的复杂应用做一个过渡。

Yii作为一个优秀的oop框架,这个例子只是介绍了它的继承,接口,mvc中的vc特性,关于数据模型,我将在后面的分析中陆续给出。最终的目标,是利用yii框架简化我们的开发过程。

好了,今天的分析就在到了,如果有什么不妥的,请留言,如果觉得有帮助,请顺手点个推荐!

以上就介绍了YII 的源码分析(-),包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート