ホームページ >PHPフレームワーク >ThinkPHP >ThinkPHPフレームワーク実行処理(ブレインマップあり)
「この記事では主にフレームワークの実行処理を紹介します。
」
フレームワークがどのように実行されるかを知らない場合、ほとんどのコードはコードを理解するだけで済みます。ソース コードを読むことは設計を学ぶことです。フレームワークのアイデアとコード パターン。
実行プロセスは、学んだことを結び付けて理解を深めます。また、Kaka は実行プロセスをマインド マップの形式で描画します。
皆さんがこの記事から少しでも知識を学べれば、カカは満足するでしょう。
このフローチャートは初期化の実行処理のみですが、残りの実行処理は後ほど補足し、マインドマップとして皆さんに提示します。
次に、ファイル thinkphp/library/think/App.php
の run メソッドを入力します。このメソッドでは、メイン画面がは次のようになります。 ボックスが描画されたところで、initialize メソッドが実行されます。
initialize メソッドについて、まず前半を見てみましょう。
microtime(true);
unix のマイクロ秒数を返しますmemory_get_usage
内容返されるのは、PHP に割り当てられたメモリ量 (バイト単位)です。static::setInstance($this);
これは、アプリ インスタンスをコンテナ インスタンスとして設定します$this->instance('app' , $this);
これは、アプリ クラスをコンテナーにバインドするために、前のコンテナーの章で説明されました (登録ツリー モード)。 $this->env とそれに続く
$this->config について疑問を持っている人はいますか。
疑問がある場合は、Kaka に従って読んでください。疑問がなければ、読み続けてください。
App クラスは継承されたコンテナー クラスであるため、env と config にはアプリにもコンテナー クラスにもこれら 2 つの属性がありません。
では、どうすれば直接呼び出すことができるのでしょうか?そして、コード追跡は env クラスとコンテナー クラスまで追跡されます。
このソースを知るには、コンテナ クラスのコードを大まかに調べる必要があります。
じっくり読んでみると、次のような数行が表示されます。下の図のコード。これらのコード行はすべてマジック メソッドを使用しています。
アクセスしたenvクラスが存在しない場合、makeメソッドが実行されます。
make メソッドについてはコンテナの章で詳しく説明されているため、詳しく説明することはできません。
この make メソッドは最終的にクラスのインスタンスを返し、コンテナーに保存されます。
ここには make メソッドのコードを 1 つだけ記述します。方法がわからない場合は、前の記事を参照してください。
最後のステップは、一連のデータをロードすることです。ロードの詳細については、序文のマインド マップを参照してください。
これは init メソッドを使用したデモです。
init メソッドはアプリケーションまたはモジュールを初期化するメソッドですが、ここでの module パラメーターは null 値を持ちます。
まず、関連するデータ情報を表示するためのブレークポイントを作成します。
出力された結果は空です。このメソッドは 1 回しか呼び出すことができないため、これは一部の新しい学習パートナーが犯す間違いです。
初期化モジュールがすべて空の場合、このメソッドが存在する必要はありません。
すると、正しいブレークポイント メソッドは次のようになります。
この時点で問題が発生します。この init メソッドは明らかに 2 回呼び出されます。では、もう 1 つの呼び出しはどこにあるのでしょうか。
新しい手法を知らない場合は、init の上位レベルで出力するなど、一連のブレークポイントを出力して、どこで実行が実行されるかを確認します。
つまり、initialize メソッドでブレークポイントを出力しますが、これは非常に面倒で、正しい場所が見つからずに多くの時間を浪費する可能性があります。
ヒント: debug_backtrace()
このメソッドは、メソッドのすべての呼び出し位置を示すバックトレースを生成します。
使用方法は以下の通りで、debug_backtrace メソッドを出力するだけです。
# 取得したデータ情報をもとに、高速に測位を行うことができます。 最初は app クラスの 215 行目です。2 回目は thinkphp/library/think/route/dispatch/Module.php
です。 class 行 60
ここで出力して、このモジュールがインデックスかどうかを確認できます
したがって、この方法を使用すると、発信場所を非常に迅速に見つけることができます。
上記はちょっとしたトリックを提供しますdebug_backtrace
メソッドが実行される場所を表示する方法の実践的なデモンストレーション。
また、次のステップでは init メソッドを深く理解する必要があるため、このケースでは init メソッドを使用してデモンストレーションを行います。
init メソッドで行われる主な処理は、上記のマインド マップで明確に説明されています。
bindTo
メソッドを使用します。 env
内部の環境変数設定になります。最後に 最初のステップは、コンテナ内のオブジェクト インスタンスの構成を更新することです (具体的な更新内容については後ほど詳しく説明します)。 <span style="display: block; background: url(https://files.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * 初始化应用或模块<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@access</span> public<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span> string $module 模块名<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@return</span> void<br/> */</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">init</span><span class="hljs-params" style="line-height: 26px;">($module = <span class="hljs-string" style="color: #98c379; line-height: 26px;">''</span>)</span><br/> </span>{<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 定位模块目录</span><br/> $module = $module ? $module . DIRECTORY_SEPARATOR : <span class="hljs-string" style="color: #98c379; line-height: 26px;">''</span>;<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * 第一次:D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\<br/> * 第二次:D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\index\<br/> */</span><br/> $path = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->appPath . $module;<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 加载初始化文件</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_file($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'init.php'</span>)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'init.php'</span>;<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">elseif</span> (is_file(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->runtimePath . $module . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'init.php'</span>)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->runtimePath . $module . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'init.php'</span>;<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 加载行为扩展文件</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_file($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'tags.php'</span>)) {<br/> $tags = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'tags.php'</span>;<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_array($tags)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->hook->import($tags);<br/> }<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 加载公共文件</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_file($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'common.php'</span>)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include_once</span> $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'common.php'</span>;<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-string" style="color: #98c379; line-height: 26px;">''</span> == $module) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 加载系统助手函数</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->thinkPath . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'helper.php'</span>;<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 加载中间件</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_file($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'middleware.php'</span>)) {<br/> $middleware = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'middleware.php'</span>;<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_array($middleware)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->middleware->import($middleware);<br/> }<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 注册服务的容器对象实例</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_file($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'provider.php'</span>)) {<br/> $provider = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">include</span> $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'provider.php'</span>;<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_array($provider)) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bindTo($provider);<br/> }<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * $path : "D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\"<br/> * "D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\index\"<br/> */</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 自动读取配置文件</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (is_dir($path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'config'</span>)) {<br/> $dir = $path . <span class="hljs-string" style="color: #98c379; line-height: 26px;">'config'</span> . DIRECTORY_SEPARATOR;<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">elseif</span> (is_dir(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->configPath . $module)) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\config\</span><br/> $dir = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->configPath . $module;<br/> }<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// scandir:以升序的方式读取目录中的文件</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 返回就是config目录中的所有文件</span><br/> $files = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>($dir) ? scandir($dir) : [];<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">foreach</span> ($files <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">as</span> $file) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * $this->configExt:配置文件的后缀<br/> * pathinfo返回的是文件后缀,关于pathinfo共有三个可选的参数PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION,分别为只返回文件名,文件目录名,文件扩展<br/> */</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-string" style="color: #98c379; line-height: 26px;">'.'</span> . pathinfo($file, PATHINFO_EXTENSION) === <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->configExt) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * 俩个参数分别为<br/> * 1.目录+config目录下的文件<br/> * 2.config目录下文件名<br/> */</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));<br/> }<br/> }<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->setModulePath($path);<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($module) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 对容器中的对象实例进行配置更新</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->containerConfigUpdate($module);<br/> }<br/> }<br/></code>
Kaka は、モジュールをセットアップするステップにおいて、init メソッドが実行されるため、それほど厳密であるとは感じません。 2か所で実装します。 初めてモジュールが空の場合、このコードを実行しても意味がありません。
以下はコンテナのオブジェクトインスタンスの設定を更新する際にモジュールのパラメータが空かどうかの判定で、空でない場合は実行されます。
同じ理由で、Kaka はモジュール パスの設定もこの判断に含めるべきだと考えています。
2 回目の実行では最初の結果が上書きされますが、Kaka は以下の図のように使用したほうが良いと感じています。
メソッドを追跡すると、Db クラスに config 属性が割り当てられ、 Database Db クラスに config 属性を与えます。
追跡メソッド $this->middleware->setConfig()ミドルウェア クラスに戻ると、このクラスの構成が次のとおりであることがわかります。渡されたパラメータ クラスとマージされ、config 属性の値も割り当てられます。
上記の場合、Db クラスの init メソッドによって達成される効果は一貫しています。
ここで言及したいのは、コンテナ内のオブジェクト インスタンスの構成を更新することです。この図では、紫色の部分がこのクラスで参照されていないことがわかります。
デバッグ モード
最初のセクションでは、初期化メソッドの前半のみについて説明します。これは、このセクション以前の話はすべてアプリケーションの初期化 init コンテンツに関するものであったためです。 次にこのセクションの内容を簡単に説明します。#上邊這三個先暫時認識就行,後期如果有機會會專門出一篇文章做解釋的。
關於框架程式碼冗餘
這裡也僅僅代表咔咔咔個人的觀點。
可以先看看這部分的程式碼,這兩個處程式碼是不是很熟悉,沒錯就是在上文的init方法中容器物件實例配置更新看到過。
如圖
這塊也就是喀喀爾個人提出的見解,由於喀喀爾式針對5.1做的源碼解讀,不太了解新版版是否做出了改動。
#本節主要是針對框架執行流程中的初始化應用做了簡單的探討。
至於在app類別的run方法下面還有很多的執行過程在這一節中沒有做過多的解釋。
在閱讀原始碼的過程中給大家提了一個很好得小技巧,那就是如何去查看一個方法都在哪裡進行了執行。
這個方法為debug_backtrace
,這個方法需要大家多使用幾次就知道怎麼使用了,因為在列印出來的結果中也存在著很多無用的資訊。
這個方法在偵錯原始碼的過程中是非常有效的,一定要好好利用這個方法。
在就是對初始化應用init方法進行了特別詳細的介紹。
其中咔咔感覺這塊設計最好的就是在容器中的物件實例進行更新配置那一塊,先讀取所有的配置,然後在通過各個類別的方法進行配置的設定。
這種程式碼規劃和設計想法值得我們去學習。
最後聊到了調試模式和框架的程式碼冗餘問題,關於調試模式這裡咔咔給大家提個醒項目在線上的調試模式一定要關閉。
否則你的專案就類似裸奔的存在,沒有一點點的安全可言。
這塊有點不好理解的就是對於緩衝區,關於這塊的內容咔咔認為暫時沒有必要去鑽牛角尖,先認識認識然後在進行深入的研究。
緩衝區的這塊內容估計工作了三四年的也很少有人使用,所以先認識,知道怎麼一回事,咔咔後期學習了之後在給大家進行補充。
直到這裡關於框架的執行流程之初始化應用就結束了,這一節沒有過深需要學習的,主要是其中的程式碼設計模式和實作思路。
最後這張圖大家一定要跟著原始碼看一看哈!
#「#堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
”
以上がThinkPHPフレームワーク実行処理(ブレインマップあり)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。