前言
可能在大家經常使用架構,寫一個Controller
或者Model
的時候,寫了好多use
,但是並沒有寫檔案載入的代碼,就以為use可以進行檔案的自動載入了。
詳細介紹
其實,現在流行的php架構,都是基於MVC模式的,大量的使用了命名空間,以提高程式的靈活性。那麼架構是怎麼實現將use關鍵字所聲明的類庫對應的指令檔進行載入的那?
(1):在通過use
關鍵字進行聲明類庫的聲明的時候,並不會進行指令碼的載入,而是在指令檔真正使用到所對應的類庫的時候才會進行載入(這就是所謂消極式載入)。
(2):架構一般在初始化階段,就聲明了__autoload()
函數或者是spl_autoload_register()
函數(一般會在入口檔案中進行聲明)。在調用通過use聲明的類庫的時候,會自動的調用上述的函數,將調用的類庫名稱傳遞到函數中(這裡的類庫名稱是包括命名空間的全名稱)
<?phpnamespace Home\Controller;function __autoload($class_name) { //echo $class_name."<br/>"; require_once ("./".$class_name . ".php"); }use Admin\Controller\Index;new Index; //new Index會觸發__autoload()函數,返回Admin\Controller\Index到函數中?>
(3):架構中定義的__autoload()
函數或者是spl_autoload_register()
函數在接收到傳遞過來的類庫名稱以後,架構會對名稱進行處理,分析出類庫名稱所對應的檔案路徑,然後進行檔案的載入。這裡需要注意的是,不同的架構在解析類庫名稱,分析檔案路徑的方式是各不一致的,畢竟各自的目錄結構是不一樣的。
比如說,thinkphp:
/** * 類庫自動載入 * @param string $class 對象類名 * @return void */ public static function autoload($class) { // 檢查是否存在映射 if(isset(self::$_map[$class])) { include self::$_map[$class]; }elseif(false !== strpos($class,'\\')){ $name = strstr($class, '\\', true); if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){ // Library目錄下面的命名空間自動定位 $path = LIB_PATH; }else{ // 檢測自訂命名空間 否則就以模組為命名空間 $namespace = C('AUTOLOAD_NAMESPACE'); $path = isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH; } $filename = $path . str_replace('\\', '/', $class) . EXT; if(is_file($filename)) { // Win環境下面嚴格區分大小寫 if (IS_WIN && false === strpos(str_replace('/', '\\', realpath($filename)), $class . EXT)){ return ; } include $filename; } }elseif (!C('APP_USE_NAMESPACE')) { // 自動載入的類庫層 foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){ if(substr($class,-strlen($layer))==$layer){ if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) { return ; } } } // 根據自動載入路徑設定進行嘗試搜尋 foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){ if(import($path.'.'.$class)) // 如果載入類成功則返回 return ; } } }
這裡只是舉例說明use與檔案的自動載入沒有關係,不強調各個架構是具體怎麼完成自動載入,具體的可以自己看架構代碼進行研究。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的協助,如果有疑問大家可以留言交流。