摘要:索性讀一下它的源碼。行載入類載入類,這個類比較重要,實現(xiàn)了自動加載。注冊錯誤和異常處理機制加載慣例配置文件接下來我們看一下自動加載的實現(xiàn)方法。所以借助此函數(shù)可以達到自動加載。博客鏈接解讀源碼一自動加載
入口聽說 TP5 已經(jīng) RC4 了,曾經(jīng)在 RC3 的時候用它寫過一個小東西。官方說從 RC4 以后改動不是太大。索性讀一下它的源碼。然后順便記錄一下,如有錯漏,請路過大神多多指正!
作為單入口框架,就從入口文件看起,按照tp5文檔所示的規(guī)范,入口文件應該是放在public/ 下。
那么為什么大多數(shù)要把入口放到子文件夾下呢?這是一個小技巧。
第一為了動靜分離,因為現(xiàn)在的php框架一般都是單入口,既然是單入口,那么必然要做rewrite,如果把靜態(tài)文件和程序文件放到一起。框架路由勢必要對每一個請求進行篩選。所以這些框架不約而同的把資源文件和程序文件區(qū)分開來,放在了不同的文件夾下。從整體來看,也就是為什么入口會在子目錄下了。
第二是為了安全,linux下的權限劃分非常嚴格,分別分為讀、寫、執(zhí)行,在這個基礎上又分為文件所有組、所在組、其他組。這樣劃分可以更好的對文件權限進行梳理,避免上傳漏洞(用戶上傳php文件被執(zhí)行)等等。
打開public/index.php
define("APP_PATH", __DIR__ . "/../application/"); // 加載框架引導文件 require __DIR__ . "/../thinkphp/start.php";
只有兩行代碼,定義 APP_PATH,加載 "/../thinkphp/start.php"。APP_PATH 可以自己修改。
然后打開 /../thinkphp/start.php
namespace think; // ThinkPHP 引導文件 // 加載基礎文件 require __DIR__ . "/base.php"; // 執(zhí)行應用 App::run()->send();
也只有三行代碼,定義命名空間,加載基礎文件,啟動應用。這里注意一下命名空間,所有thinkphp類都在think及其子命名空間下。程序中用到框架類的時候要先use 該類的命名空間;
環(huán)境配置然后我們打開base.php
12-31行定義了一坨常量。注意里面 defined("THINK_PATH") or define("THINK_PATH", __DIR__ . DS); 這種定義方式,先判斷時候存在,如果不存在則定義。也就是說我們可以在這行代碼之前(一般在index.php中)執(zhí)行定義這個常量,而不會被覆蓋。
36-37行
// 載入Loader類 require CORE_PATH . "Loader.php";
載入Loader類,這個類比較重要,實現(xiàn)了自動加載。
39-51行
// 加載環(huán)境變量配置文件 if (is_file(ROOT_PATH . "env" . EXT)) { $env = include ROOT_PATH . "env" . EXT; foreach ($env as $key => $val) { $name = ENV_PREFIX . strtoupper($key); if (is_bool($val)) { $val = $val ? 1 : 0; } elseif (!is_scalar($val)) { continue; } putenv("$name=$val"); } }
加載環(huán)境變量配置文件,可能很多同學不理解是干什么用的。
我們假設一個場景,你在公司和家里開發(fā)程序,在內(nèi)網(wǎng)服務器上進行測試,在外網(wǎng)服務器上部署,所有的配置不能可能全部相同(比如數(shù)據(jù)庫帳號密碼、文件路徑等等)??偛荒苊看味几呐渲冒??如果做負載、有幾十個服務器怎么部署?總不能都用ftp上傳,然后改配置吧?
所以現(xiàn)在主流的做法就是區(qū)分環(huán)境(開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境),然后程序自動加載不同的配置。但是通過什么區(qū)分呢?方法有很多,但是大多數(shù)都是選擇通過環(huán)境變量來區(qū)分,然后加載對應的配置文件。然后使用 git 做版本控制,然后在服務器部署同步腳本,通過 git push鉤子進行代碼同步,以達到自動化部署的模式。當然也還有其他方式,但是大多都類似。
自動加載為什么要使用自動加載呢?因為像java、C等編譯型語言在編譯過程中會把程序中引用的庫、包等等自動引入進來。但是php是腳本行語言啊,沒有編譯過程,怎么辦呢?最早期的程序都是手動引入,比如早期的xxshop、xxcms,都是寫一坨require、include。又搓又不方便,對于世界上最好的語言來說這樣多丟面啊,所以我們需要用自動加載讓我們最好的語言看起來更有B格(至于某些性能論的同學會說自動加載影響性能啊之類的,請用匯編!)。
我們繼續(xù)看base.php 的 54行 hinkLoader::register();
注冊自動加載,從這一行之后就可以使用符合自動加載規(guī)范的任何類了。
比如56-60行,雖然沒有加載對應的文件,但是通過自動加載就可以直接使用。
// 注冊錯誤和異常處理機制 hinkError::register(); // 加載慣例配置文件 hinkConfig::set(include THINK_PATH . "convention" . EXT);
接下來我們看一下自動加載的實現(xiàn)方法。打開Loader.php,按照上面的執(zhí)行順序,先看Loader類的register方法
核心是
spl_autoload_register($autoload ?: "thinkLoader::autoload", true, true); // 注冊命名空間定義 self::addNamespace([ "think" => LIB_PATH . "think" . DS, "behavior" => LIB_PATH . "behavior" . DS, "traits" => LIB_PATH . "traits" . DS, ]); // 加載類庫映射文件 if (is_file(RUNTIME_PATH . "classmap" . EXT)) { self::addClassMap(__include_file(RUNTIME_PATH . "classmap" . EXT)); }
spl_autoload_register方法可能很多同學都有了解,在我們實例化一個當前已加載文件中不存在的類后(比如在a.php中new一個類,會先在a.php和已加載的文件中找),會執(zhí)行此方法指定的函數(shù),并把類名傳遞進去。在這個函數(shù)中如果能正確加載到該文件,那么也可以實例化成功,并不會報錯。所以借助此函數(shù)可以達到自動加載。
首先我們知道當 new 一個不存在的類時,如果使用spl_autoload_register定義了一個處理函數(shù),那么這個函數(shù)可以獲得一個參數(shù),參數(shù)名是new 的類名。比如從前面base.php中我們看到 hinkError::register();使用think命名空間下的Error類的register靜態(tài)方法,但是我們并沒有引入這個文件。于是我們可以在spl_autoload_register注冊的函數(shù)中得到一個參數(shù)thinkError,如果我們的命名空間按照文件夾格式的方法命名(這也是推薦的、常用的命名方式),那么就可以通過該參數(shù)來加載對應的文件,但是如果特殊情況下沒有按照文件夾的格式來進行命名空間的命名,那么就需要手動指定映射關系。self::addClassMap(__include_file(RUNTIME_PATH . "classmap" . EXT)); 加載了映射文件。然后我們看spl_autoload_register中指定的函數(shù):autoload。
這個不用詳細解釋了,先處理由 addNamespace 設定的命名空間別名,然后通過 findFile 來處理映射關系,得到真實的路徑,并加載文件。
而__autoload()函數(shù)具有類似的功能。但是為什么用的很少呢?因為 __autoload()只能指定一個函數(shù),而spl_autoload_register可以注冊多個函數(shù)來處理這個邏輯。一旦業(yè)務復雜 __autoload()就完全不能勝任。比如我們繼續(xù)看Loader類的register方法下面的內(nèi)容
// Composer自動加載支持 if (is_dir(VENDOR_PATH . "composer")) { self::registerComposerLoader(); } // 自動加載extend目錄 self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
一個框架是否好用,很大程度取決于它的擴展能力。所以自動加載除了要處理自身類庫的加載、還要處理擴展類庫的自動加載。tp5支持使用兩種方式來擴展類庫一種是Composer,一種是手動放入 extend 目錄。
Composer不用多說,就像npm之于nodejs、yum之于Centos、apt-get之于、Ubuntu。一個php的包管理工具。Composer有一套自己的自動加載機制,tp5這里只不過是調(diào)用了Composer自己的注冊自動加載函數(shù)的方法。有興趣的同學可以看一下registerComposerLoader方法,以及vendor/composer下幾個autoload開頭的文件。原理基本上和上面的一致。
Loader.php中核心方法已經(jīng)介紹完畢,其他的幾個方法有處理規(guī)范的方法(PSR-0,PSR-2,PSR-4,有興趣的同學可以谷歌、百度了解一下)、和根據(jù)類名處理模型和控制器的方法,這點需要看完路由才能詳解。
博客鏈接:解讀 thinkphp5 源碼(一):自動加載
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/30386.html
摘要:異常處理上節(jié)解讀源碼一自動加載看完了自動加載部分,根據(jù)代碼執(zhí)行順序,的行注冊錯誤和異常處理機制加載慣例配置文件下面的加載配置文件不用說,現(xiàn)在重點看一下異常處理。博客鏈接解讀源碼二異常處理和請求生命周期 異常處理 上節(jié)解讀 thinkphp5 源碼(一):自動加載看完了自動加載部分,根據(jù)代碼執(zhí)行順序,base.php的59-64行 // 注冊錯誤和異常處理機制 hinkError::r...
摘要:如果遍歷后沒有找到,則加載失敗。在之后碰到了之后直接拿來用,提高系統(tǒng)自動加載的性能。這里我們就講完了注冊自動加載。使用自動加載我們在中定義了我們自動加載函數(shù)式方法。 繼 生命周期的第二篇,大家盡可放心,不會隨便鴿文章的 第一篇中,我們提到了入口腳本,也說了,里面注冊了自動加載的功能 本文默認你有自動加載和命名空間的基礎。如果沒有請 看此篇文章 php 類的自動加載與命名空間 自動加載...
摘要:即基于拿來即用高性能后臺管理系統(tǒng)官方文檔地址在線體驗地址賬戶密碼線上倉庫在線地址源代碼下載克隆直接下載本地部署運行環(huán)境要求建議配置虛擬域名若不清楚,請自行解決之,方便接下來開展你的開發(fā)工作。 新版本在線體驗地址已經(jīng)上線,歡迎體驗? ---2017-01-14 喜歡就Star,不只是Fork; 想要分享的動機才是驅(qū)動力,而技術僅僅是一種方法。 ====================...
摘要:即基于拿來即用高性能后臺管理系統(tǒng)官方文檔地址在線體驗地址賬戶密碼線上倉庫在線地址源代碼下載克隆直接下載本地部署運行環(huán)境要求建議配置虛擬域名若不清楚,請自行解決之,方便接下來開展你的開發(fā)工作。 新版本在線體驗地址已經(jīng)上線,歡迎體驗? ---2017-01-14 喜歡就Star,不只是Fork; 想要分享的動機才是驅(qū)動力,而技術僅僅是一種方法。 ====================...
閱讀 3162·2023-04-25 17:19
閱讀 616·2021-11-23 09:51
閱讀 1339·2021-11-08 13:19
閱讀 776·2021-09-29 09:34
閱讀 1673·2021-09-28 09:36
閱讀 1493·2021-09-22 14:59
閱讀 2707·2019-08-29 16:38
閱讀 2053·2019-08-26 13:40