PHP 架構內的控制器能隨時用設定檔裡的常量,原理是把設定檔include進來了嗎?
還有www.baidu.com/index/demo,訪問的是index控制器裡的demo方法,為什麼一個URL 就能去執行個體化一個控制器類,原理是什嗎?謝謝
回複內容:
PHP 架構內的控制器能隨時用設定檔裡的常量,原理是把設定檔include進來了嗎?
還有www.baidu.com/index/demo,訪問的是index控制器裡的demo方法,為什麼一個URL 就能去執行個體化一個控制器類,原理是什嗎?謝謝
能問出這兩個問題,說明題主在使用架構的過程中進行了深入的思考,先贊一個!
想得到這兩個問題的答案,需要對 PHP 的本質有一定的瞭解,我想展開說一下。如果能對大家有一點點協助,我就很開心了。
1. 在代碼的任何地方都能直接調用設定檔中的內容,是因為設定檔被 require 進來並賦值給了一個或多個變數。
代碼可以參考:https://github.com/TinyLara/TinyLara/blob/master/bootstrap.php#L11
PHP 作為指令碼語言,執行的本質就是把一串字串(指令)發給一個處理器,然後這個處理器根據指令執行相應的動作。多檔案的 PHP 架構也是靠的這種方式運行,require、include或者__autoload等,最終組合出來一個巨長的 PHP 代碼,由解譯器執行,得到結果。設定檔的的內容會被賦給這段巨長的 PHP 代碼中的某個 public 變數,在整個生命流程中一直可用。
2. PHP 代碼確實可以通過 URL 來執行個體化類,也可以判斷 URL 內容來判斷需要載入哪個類,執行哪個 function。
PHP 可以邊執行代碼邊載入檔案,可以根據 URL 的不同選擇不同的檔案載入。目前大多數架構都使用了 PHP 的自動載入,例如 __autoload() 魔術方法,在代碼中調用某個類的時候自動載入這個類所在的檔案。
你所問的就是 路由 的本質,直接看代碼:https://github.com/TinyLara/TinyRoute/blob/master/TinyRoute.php#L86
上面代碼中 $last = 'HomeController@home'。
不得不感歎,PHP 真是字串的藝術呀!
在PHP5之前,各個PHP架構如果要實作類別的自動載入,一般都是按照某種約定自己實現一個遍曆目錄,自動載入所有符合約定規則的檔案的類或函數。 當然,PHP5之前對物件導向的支援並不是太好,類的使用也沒有現在頻繁。 在PHP5後,當載入PHP類時,如果類所在檔案沒有被包含進來,或者類名出錯,Zend引擎會自動調用__autoload 函數。此函數需要使用者自己實現__autoload函數。 在PHP5.1.2版本後,可以使用spl_autoload_register函數自訂自動載入處理函數。當沒有調用此函數,預設情況下會使用SPL自訂的spl_autoload函數。
執行個體化一個控制器類或者是其他任何類,跟URL是沒有太大關係的。
實際的邏輯大概是這樣的:
假設這樣一個url:http://your.domain.com/path/to/your/file
那麼web伺服器收到請求後,會先搜尋your.domain.com這個網域名稱對應的根目錄是在哪裡,假設是在/www。
那麼,實際請求的檔案就是/www/path/to/your/file。如果這個檔案是php類型的,web伺服器會把檔案先交由php解譯器解釋,再把結果返回給瀏覽器。
單一入口的項目,只是通過web伺服器配置,把所有的請求都是映射到類似index.php之類的入口檔案。再由程式的邏輯去解析url後面的參數,再決定執行個體化哪個控制器,或者是調用其他方法。
第二個問題,你說對了, 本質還是 include
是的,已yii為例,他的設定檔是一個數組,在架構一開始就載入了設定檔。
當請求一個控制器/方法時,會根據架構的註冊的autoload尋找controller,找到就引用,繼續找方法,找不到就報異常。
本人是通過把配置資訊寫在一個介面類裡了,
然後通過spl_authload載入這個類,
調用的時候,先繼承這個類,然後直接self::xxx
先將 path context 和 controller class 綁定,如果訪問路徑與某個 path context 匹配,就執行個體化 controller class.