亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

解讀 thinkphp5 源碼(一):自動(dòng)加載

stormzhang / 3339人閱讀

摘要:索性讀一下它的源碼。行載入類載入類,這個(gè)類比較重要,實(shí)現(xiàn)了自動(dòng)加載。注冊(cè)錯(cuò)誤和異常處理機(jī)制加載慣例配置文件接下來(lái)我們看一下自動(dòng)加載的實(shí)現(xiàn)方法。所以借助此函數(shù)可以達(dá)到自動(dòng)加載。博客鏈接解讀源碼一自動(dòng)加載

聽(tīng)說(shuō) TP5 已經(jīng) RC4 了,曾經(jīng)在 RC3 的時(shí)候用它寫過(guò)一個(gè)小東西。官方說(shuō)從 RC4 以后改動(dòng)不是太大。索性讀一下它的源碼。然后順便記錄一下,如有錯(cuò)漏,請(qǐng)路過(guò)大神多多指正!

入口

作為單入口框架,就從入口文件看起,按照tp5文檔所示的規(guī)范,入口文件應(yīng)該是放在public/ 下。

那么為什么大多數(shù)要把入口放到子文件夾下呢?這是一個(gè)小技巧。

第一為了動(dòng)靜分離,因?yàn)楝F(xiàn)在的php框架一般都是單入口,既然是單入口,那么必然要做rewrite,如果把靜態(tài)文件和程序文件放到一起??蚣苈酚蓜?shì)必要對(duì)每一個(gè)請(qǐng)求進(jìn)行篩選。所以這些框架不約而同的把資源文件和程序文件區(qū)分開(kāi)來(lái),放在了不同的文件夾下。從整體來(lái)看,也就是為什么入口會(huì)在子目錄下了。

第二是為了安全,linux下的權(quán)限劃分非常嚴(yán)格,分別分為讀、寫、執(zhí)行,在這個(gè)基礎(chǔ)上又分為文件所有組、所在組、其他組。這樣劃分可以更好的對(duì)文件權(quán)限進(jìn)行梳理,避免上傳漏洞(用戶上傳php文件被執(zhí)行)等等。

打開(kāi)public/index.php

define("APP_PATH", __DIR__ . "/../application/");
// 加載框架引導(dǎo)文件
require __DIR__ . "/../thinkphp/start.php";

只有兩行代碼,定義 APP_PATH,加載 "/../thinkphp/start.php"。APP_PATH 可以自己修改。

然后打開(kāi) /../thinkphp/start.php

namespace think;
// ThinkPHP 引導(dǎo)文件
// 加載基礎(chǔ)文件
require __DIR__ . "/base.php";
// 執(zhí)行應(yīng)用
App::run()->send();

也只有三行代碼,定義命名空間,加載基礎(chǔ)文件,啟動(dòng)應(yīng)用。這里注意一下命名空間,所有thinkphp類都在think及其子命名空間下。程序中用到框架類的時(shí)候要先use 該類的命名空間;

環(huán)境配置

然后我們打開(kāi)base.php
12-31行定義了一坨常量。注意里面 defined("THINK_PATH") or define("THINK_PATH", __DIR__ . DS); 這種定義方式,先判斷時(shí)候存在,如果不存在則定義。也就是說(shuō)我們可以在這行代碼之前(一般在index.php中)執(zhí)行定義這個(gè)常量,而不會(huì)被覆蓋。

36-37行

// 載入Loader類
require CORE_PATH . "Loader.php";

載入Loader類,這個(gè)類比較重要,實(shí)現(xiàn)了自動(dòng)加載。

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)境變量配置文件,可能很多同學(xué)不理解是干什么用的。

我們假設(shè)一個(gè)場(chǎng)景,你在公司和家里開(kāi)發(fā)程序,在內(nèi)網(wǎng)服務(wù)器上進(jìn)行測(cè)試,在外網(wǎng)服務(wù)器上部署,所有的配置不能可能全部相同(比如數(shù)據(jù)庫(kù)帳號(hào)密碼、文件路徑等等)??偛荒苊看味几呐渲冒??如果做負(fù)載、有幾十個(gè)服務(wù)器怎么部署?總不能都用ftp上傳,然后改配置吧?

所以現(xiàn)在主流的做法就是區(qū)分環(huán)境(開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境),然后程序自動(dòng)加載不同的配置。但是通過(guò)什么區(qū)分呢?方法有很多,但是大多數(shù)都是選擇通過(guò)環(huán)境變量來(lái)區(qū)分,然后加載對(duì)應(yīng)的配置文件。然后使用 git 做版本控制,然后在服務(wù)器部署同步腳本,通過(guò) git push鉤子進(jìn)行代碼同步,以達(dá)到自動(dòng)化部署的模式。當(dāng)然也還有其他方式,但是大多都類似。

自動(dòng)加載

為什么要使用自動(dòng)加載呢?因?yàn)橄駄ava、C等編譯型語(yǔ)言在編譯過(guò)程中會(huì)把程序中引用的庫(kù)、包等等自動(dòng)引入進(jìn)來(lái)。但是php是腳本行語(yǔ)言啊,沒(méi)有編譯過(guò)程,怎么辦呢?最早期的程序都是手動(dòng)引入,比如早期的xxshop、xxcms,都是寫一坨require、include。又搓又不方便,對(duì)于世界上最好的語(yǔ)言來(lái)說(shuō)這樣多丟面啊,所以我們需要用自動(dòng)加載讓我們最好的語(yǔ)言看起來(lái)更有B格(至于某些性能論的同學(xué)會(huì)說(shuō)自動(dòng)加載影響性能啊之類的,請(qǐng)用匯編!)。

我們繼續(xù)看base.php 的 54行 hinkLoader::register();
注冊(cè)自動(dòng)加載,從這一行之后就可以使用符合自動(dòng)加載規(guī)范的任何類了。

比如56-60行,雖然沒(méi)有加載對(duì)應(yīng)的文件,但是通過(guò)自動(dòng)加載就可以直接使用。

// 注冊(cè)錯(cuò)誤和異常處理機(jī)制
	hinkError::register();
// 加載慣例配置文件
	hinkConfig::set(include THINK_PATH . "convention" . EXT);

接下來(lái)我們看一下自動(dòng)加載的實(shí)現(xiàn)方法。打開(kāi)Loader.php,按照上面的執(zhí)行順序,先看Loader類的register方法

核心是

spl_autoload_register($autoload ?: "thinkLoader::autoload", true, true);
// 注冊(cè)命名空間定義
self::addNamespace([
    "think"    => LIB_PATH . "think" . DS,
    "behavior" => LIB_PATH . "behavior" . DS,
    "traits"   => LIB_PATH . "traits" . DS,
]);
// 加載類庫(kù)映射文件
if (is_file(RUNTIME_PATH . "classmap" . EXT)) {
    self::addClassMap(__include_file(RUNTIME_PATH . "classmap" . EXT));
}

spl_autoload_register方法可能很多同學(xué)都有了解,在我們實(shí)例化一個(gè)當(dāng)前已加載文件中不存在的類后(比如在a.php中new一個(gè)類,會(huì)先在a.php和已加載的文件中找),會(huì)執(zhí)行此方法指定的函數(shù),并把類名傳遞進(jìn)去。在這個(gè)函數(shù)中如果能正確加載到該文件,那么也可以實(shí)例化成功,并不會(huì)報(bào)錯(cuò)。所以借助此函數(shù)可以達(dá)到自動(dòng)加載。

首先我們知道當(dāng) new 一個(gè)不存在的類時(shí),如果使用spl_autoload_register定義了一個(gè)處理函數(shù),那么這個(gè)函數(shù)可以獲得一個(gè)參數(shù),參數(shù)名是new 的類名。比如從前面base.php中我們看到 hinkError::register();使用think命名空間下的Error類的register靜態(tài)方法,但是我們并沒(méi)有引入這個(gè)文件。于是我們可以在spl_autoload_register注冊(cè)的函數(shù)中得到一個(gè)參數(shù)thinkError,如果我們的命名空間按照文件夾格式的方法命名(這也是推薦的、常用的命名方式),那么就可以通過(guò)該參數(shù)來(lái)加載對(duì)應(yīng)的文件,但是如果特殊情況下沒(méi)有按照文件夾的格式來(lái)進(jìn)行命名空間的命名,那么就需要手動(dòng)指定映射關(guān)系。self::addClassMap(__include_file(RUNTIME_PATH . "classmap" . EXT)); 加載了映射文件。然后我們看spl_autoload_register中指定的函數(shù):autoload。
這個(gè)不用詳細(xì)解釋了,先處理由 addNamespace 設(shè)定的命名空間別名,然后通過(guò) findFile 來(lái)處理映射關(guān)系,得到真實(shí)的路徑,并加載文件。

__autoload()函數(shù)具有類似的功能。但是為什么用的很少呢?因?yàn)?__autoload()只能指定一個(gè)函數(shù),而spl_autoload_register可以注冊(cè)多個(gè)函數(shù)來(lái)處理這個(gè)邏輯。一旦業(yè)務(wù)復(fù)雜 __autoload()就完全不能勝任。比如我們繼續(xù)看Loader類的register方法下面的內(nèi)容

        // Composer自動(dòng)加載支持
        if (is_dir(VENDOR_PATH . "composer")) {
            self::registerComposerLoader();
        }
        // 自動(dòng)加載extend目錄
        self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);

一個(gè)框架是否好用,很大程度取決于它的擴(kuò)展能力。所以自動(dòng)加載除了要處理自身類庫(kù)的加載、還要處理擴(kuò)展類庫(kù)的自動(dòng)加載。tp5支持使用兩種方式來(lái)擴(kuò)展類庫(kù)一種是Composer,一種是手動(dòng)放入 extend 目錄。
Composer不用多說(shuō),就像npm之于nodejs、yum之于Centos、apt-get之于、Ubuntu。一個(gè)php的包管理工具。Composer有一套自己的自動(dòng)加載機(jī)制,tp5這里只不過(guò)是調(diào)用了Composer自己的注冊(cè)自動(dòng)加載函數(shù)的方法。有興趣的同學(xué)可以看一下registerComposerLoader方法,以及vendor/composer下幾個(gè)autoload開(kāi)頭的文件。原理基本上和上面的一致。

Loader.php中核心方法已經(jīng)介紹完畢,其他的幾個(gè)方法有處理規(guī)范的方法(PSR-0,PSR-2,PSR-4,有興趣的同學(xué)可以谷歌、百度了解一下)、和根據(jù)類名處理模型和控制器的方法,這點(diǎn)需要看完路由才能詳解。

博客鏈接:解讀 thinkphp5 源碼(一):自動(dòng)加載

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/30386.html

相關(guān)文章

  • 解讀 thinkphp5 源碼(二):異常處理和請(qǐng)求生命周期

    摘要:異常處理上節(jié)解讀源碼一自動(dòng)加載看完了自動(dòng)加載部分,根據(jù)代碼執(zhí)行順序,的行注冊(cè)錯(cuò)誤和異常處理機(jī)制加載慣例配置文件下面的加載配置文件不用說(shuō),現(xiàn)在重點(diǎn)看一下異常處理。博客鏈接解讀源碼二異常處理和請(qǐng)求生命周期 異常處理 上節(jié)解讀 thinkphp5 源碼(一):自動(dòng)加載看完了自動(dòng)加載部分,根據(jù)代碼執(zhí)行順序,base.php的59-64行 // 注冊(cè)錯(cuò)誤和異常處理機(jī)制 hinkError::r...

    yuanzhanghu 評(píng)論0 收藏0
  • ThinkPHP5.1 源碼淺析(二)自動(dòng)加載機(jī)制

    摘要:如果遍歷后沒(méi)有找到,則加載失敗。在之后碰到了之后直接拿來(lái)用,提高系統(tǒng)自動(dòng)加載的性能。這里我們就講完了注冊(cè)自動(dòng)加載。使用自動(dòng)加載我們?cè)谥卸x了我們自動(dòng)加載函數(shù)式方法。 繼 生命周期的第二篇,大家盡可放心,不會(huì)隨便鴿文章的 第一篇中,我們提到了入口腳本,也說(shuō)了,里面注冊(cè)了自動(dòng)加載的功能 本文默認(rèn)你有自動(dòng)加載和命名空間的基礎(chǔ)。如果沒(méi)有請(qǐng) 看此篇文章 php 類的自動(dòng)加載與命名空間 自動(dòng)加載...

    mudiyouyou 評(píng)論0 收藏0
  • TP-admin即基于ThinkPHP5拿來(lái)即用高性能后臺(tái)管理系統(tǒng)

    摘要:即基于拿來(lái)即用高性能后臺(tái)管理系統(tǒng)官方文檔地址在線體驗(yàn)地址賬戶密碼線上倉(cāng)庫(kù)在線地址源代碼下載克隆直接下載本地部署運(yùn)行環(huán)境要求建議配置虛擬域名若不清楚,請(qǐng)自行解決之,方便接下來(lái)開(kāi)展你的開(kāi)發(fā)工作。 新版本在線體驗(yàn)地址已經(jīng)上線,歡迎體驗(yàn)? ---2017-01-14 喜歡就Star,不只是Fork; 想要分享的動(dòng)機(jī)才是驅(qū)動(dòng)力,而技術(shù)僅僅是一種方法。 ====================...

    Hydrogen 評(píng)論0 收藏0
  • TP-admin即基于ThinkPHP5拿來(lái)即用高性能后臺(tái)管理系統(tǒng)

    摘要:即基于拿來(lái)即用高性能后臺(tái)管理系統(tǒng)官方文檔地址在線體驗(yàn)地址賬戶密碼線上倉(cāng)庫(kù)在線地址源代碼下載克隆直接下載本地部署運(yùn)行環(huán)境要求建議配置虛擬域名若不清楚,請(qǐng)自行解決之,方便接下來(lái)開(kāi)展你的開(kāi)發(fā)工作。 新版本在線體驗(yàn)地址已經(jīng)上線,歡迎體驗(yàn)? ---2017-01-14 喜歡就Star,不只是Fork; 想要分享的動(dòng)機(jī)才是驅(qū)動(dòng)力,而技術(shù)僅僅是一種方法。 ====================...

    Aklman 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<