Phalcon自動載入(PHP自動載入)

来源:http://www.cnblogs.com/mengxuan/archive/2016/01/17/5137881.html
-Advertisement-
Play Games

自動載入(phalcon\Loader)轉載請註明來源一、php文件引入 通過 include() 或 require() 函數,可以在PHP程式執行之前在該文件中插入一個文件的內容。區別:處理錯誤的方式不同。include() 函數會生成一個警告(但是腳本會繼續執行),而 require() 函....


自動載入(phalcon\Loader)


轉載請註明來源

一、php文件引入

  通過 include() 或 require() 函數,可以在PHP程式執行之前在該文件中插入一個文件的內容。

區別:處理錯誤的方式不同include() 函數會生成一個警告(但是腳本會繼續執行),而 require() 函數會生成一個致命錯誤(fatal error)(在錯誤發生後腳本會停止執行)

  * 正因為在文件不存在或被重命名後腳本不會繼續執行,因此我們推薦使用 require() 而不是 include()。

二、php類自動載入

參考文章:php手冊  和  PHP的類自動載入機制

  在php5之前,各php框架實現類的載入,一般要按照某種約定實現一個遍歷目錄,自動載入符合約定條件的文件類或函數。因此在php5之前類的使用並沒有現在頻繁。

  在php5之後,當載入php類的時候,如果類所在文件夾並沒有被包含進來或是類名出錯時,Zend引擎會自動調用__autoload函數。__autoload函數需要用戶自己實現。

  在php5.1.2版本之後,可以使用spl_autoload_register函數自定義載入處理函數。當沒有調用此函數,預設情況下會使用spl自定義的spl_autoload函數。

 

1. php自動載入之__autoload

 

function __autoload($className) {
    $file = $className . '.php';
    if (is_file($file)) {
        require($file);
    }else{
        echo 'no this ' . $className . ' class file';
    }
}
$demo = new Demo();

 事實上,我們可以看到__autoload至少需要做三件事(“三步走”),它們分別是:

  1. 根據類名確定類的文件名。
  2. 確定類文件所在路徑,上例用的是中用的是相對定位,我們的測試文件其實在同一目錄下。
  3. 將指定類所在文件載入到程式中。

在第一步和第二步中,我們必須約定類名與文件的映射方法,只有這樣我們才能夠依據類名找到其所對應的文件,實現載入。

因此__autoload自動載入中,最重要的就是指定類名與其所在文件的對應關係。當有大量的類需要包含進來的時候,我們只需要確立相應的規則,然後將類名與其對應的文件進行映射,就能夠實現惰性載入(lazy loading)了。

Tip:spl_autoload_register() 提供了一種更加靈活的方式來實現類的自動載入。因此,不再建議使用 __autoload() 函數,在以後的版本中它可能被棄用。

2. php自動載入之spl_autoload_register

引言:如果在一個php系統實現中,使用了很多的其他類庫,這些類庫可能是由不同的工程師進行開發的,因此類名與其所在文件的映射規則不盡相同。這時候如果要實現類庫的自動載入,就必須在__autoload函數中將所有的映射規則全部實現。這就會導致__autoload會非常複雜,甚至無法實現。同時還會使得__autoload函數十分臃腫。為將來系統的維護和性能帶來很大的負面影響。(__autoload的弊端)

spl_autoload_register:

  註冊給定的函數作為__autoload的實現。簡單來說就是將函數註冊之SPL的__autoload函數棧中,並移除系統預設的__autload()函數。

function __autoload($className) {  
    echo 'autload class:', $className, '<br />';  
}  
function classLoader($className) {  
    echo 'SPL load class:', $className, '<br />';  
}  
spl_autoload_register('classLoader');  
new Test();//結果:SPL load class:Test 

 

Tip:

  1. 如果在你的程式中已經實現了__autoload()函數,它必須顯式註冊到__autoload()隊列中。因為 spl_autoload_register()函數會將Zend Engine中的__autoload()函數取代為spl_autoload()或spl_autoload_call()。
  2. 相比於__autoload只能夠定義一次。spl_autoload_register()函數可以定義多個autoload函數。因為spl_autoload_register創建了autoload函數隊列,該隊列按照定義的先後順序逐個執行。

     function __autoload($className) {  
         echo 'autload class:' . $className . '<br />';  
     }  
     function classLoader($className) {  
         echo 'SPL load class:' . $className . '<br />';  
     }  
     spl_autoload_register('classLoader');  
     $demo = new Demo();//結果:SPL load class:Demo
    

函數說明

bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
  • autoload_function【可選】添加到自動載入棧的函數。預設為spl_autoload()。
    • 還可以調用spl_autoload_register()函數以註冊一個回調函數,而不是為函數提供一個字元串名稱。如提供一個如array('class','method')這樣的數組,使得可以使用某個對象的方法
  • throw【可選】無法成功註冊時,是否拋出異常
  • prepend【可選】是否將將該函數添加到隊列之首,而不是隊列的尾部。

備註:SPL自動載入功能是由spl_autoload() ,spl_autoload_register(), spl_autoload_functions() ,spl_autoload_extensions()和spl_autoload_call()函數提供的。

三、Phalcon的類自動載入

Phalcon\Loader 通用類載入器(Universal Class Loader),意在根據協議幫助項目自動載入項目中的類(This component helps to load your project classes automatically based on some conventions)。Phalcon支持四種類載入方式,先後順序分別是註冊類名、註冊命名空間、註冊首碼和註冊文件夾的方式。

Phalcon的預設文件尾碼為php,當然你自己也可以配置(setExtensions())。

1 . 註冊類名

<?php
$loader = new \Phalcon\Loader();
$loader->registerClasses(
    array(
        "Some"         => "library/OtherComponent/Other/Some.php",
        "Example\Base" => "vendor/example/adapters/Example/BaseClass.php",
    )
);
$loader->register();    
// i.e. library/OtherComponent/Other/Some.php
$some = new Some();

 

  1. 最快的自動方法
  2. 不利於維護

具體實現:

  1. 判斷是否有類被註冊。
  2. 判斷需要載入的類是否被註冊,如果已註冊則載入其對應路徑文件。

2. 註冊命名空間

<?php
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(
    array(
       "Example\Base"    => "vendor/example/base/",
       "Example\Adapter" => "vendor/example/adapter/",
       "Example"         => "vendor/example/",
    )
);
$loader->register();
// vendor/example/adapter/Some.php
$some = new Example\Adapter\Some();

 

使用命名空間或外部庫組織代碼時,你可以利用註冊命名空間的方式來自動載入其包含的庫。

對於命名空間對應的路徑,要其末尾加一個斜杠。

具體實現:

  1. 判斷是否有命名空間被註冊。
  2. 判斷需要載入的類是否已以註冊的命名開始。

    例如註冊的命名空間為"Example\Base" => "vendor/example/base/"

    "Example\Base"    => "vendor/example/base/"
     $test1 = new Example\Base\Test();// vendor/example/base/Test.php
     $test2 = new Example\Test();// 錯誤,無法載入。

     

    名稱處理:1、去掉命名指定空間首碼。2、將命名空間分隔符\轉換成文件分隔符/

  3. 依據文件拓展名構建完整的文件路徑,並判斷該文件是否存在,如該文件存在載入。

3. 註冊首碼

<?php
$loader = new \Phalcon\Loader();
$loader->registerPrefixes(
    array(
       "Example_Base"     => "vendor/example/base/",
       "Example_Adapter"  => "vendor/example/adapter/",
       "Example_"         => "vendor/example/",
    )
);    
$loader->register();    
// vendor/example/adapter/Some.php
$some = new Example_Adapter_Some();

 

類似於命名空間,從2.1.0開始phalcon將不再支持首碼。

具體實現:

  1. 判斷是否有首碼被註冊。
  2. 判斷需要載入的類是否已以首碼開始命名。

    例如註冊的首碼為"Example_Base" => "vendor/example/base/"

    "Example_Base"    => "vendor/example/base/"
     $test1 = new Example_Base_Test();// vendor/example/base/Test.php
     $test2 = new Example_Test();// 錯誤,無法載入。

     

    名稱處理:1、去掉類的首碼。2、將首碼分隔符_轉換成文件分隔符/

  3. 依據文件拓展名構建完整的文件路徑,並判斷該文件是否存在,如該文件存在載入。

4. 註冊文件夾

<?php
$loader = new \Phalcon\Loader();    
$loader->registerDirs(
    array(
        "library/MyComponent/",
        "library/OtherComponent/Other/",
        "vendor/example/adapters/",
        "vendor/example/"
    )
);    
$loader->register();    
// i.e. library/OtherComponent/Other/Some.php
$some = new Some();

 

可以自動載入註冊目錄下的類文件。但是該方法在性能方面並不被推薦,因為Phalcon將在個文件夾下大量查找與類名相同的文件。在使用註冊目錄自動載入時,要註意註冊目錄的相關性,即將重要的目錄放在前面。

具體實現:

  1. 將類名中的首碼分隔符_或是命名空間分隔符\替換成文件夾分割符/
  2. 判斷是否有文件夾被註冊。
  3. 依據文件尾碼構建可能的文件路徑

    例如註冊的首碼為"vendor/example/base/"

     $test = new Test();// vendor/example/base/Test.php

     

5. 修改當前策略(Modifying current strategies)

即為當前自動載入數據添加額外的值。

<?php
// Adding more directories
$loader->registerDirs(
    array(
        "../app/library/",
        "../app/plugins/"
    ),
    true
);

 

註冊時添加第二個參數值true,使其與原數組合併。

6. 安全層(Security Layer)

沒有進行任何安全檢查的自動載入器,如下:

<?php
//Basic autoloader
spl_autoload_register(function($className) {
    if (file_exists($className . '.php')) {
        require $className . '.php';
    }
});

 

假如我們沒有進行任何安全檢查時,如果誤啟了自動載入器,那麼惡意準備的字元串就回作為參數訪問程式中的重要文件。

<?php

//This variable is not filtered and comes from an insecure source
$className = '../processes/important-process';

//Check if the class exists triggering the auto-loader
if (class_exists($className)) {
    //...
}

 

Phalcon的做法是刪除任何無用的字元串,減少被攻擊的可能性。

7. 自動載入事件

在下麵的例子中,而不必使用類載入器,使我們獲得調試信息的流程操作:

<?php
$eventsManager = new \Phalcon\Events\Manager();
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
       'Example\\Base' => 'vendor/example/base/',
       'Example\\Adapter' => 'vendor/example/adapter/',
       'Example' => 'vendor/example/'
));
//Listen all the loader events
$eventsManager->attach('loader', function($event, $loader) {
    if ($event->getType() == 'beforeCheckPath') {
        echo $loader->getCheckedPath();
    }
});
$loader->setEventsManager($eventsManager);
$loader->register();

 

Phalcon自動載入支持以下事件:

  • beforeCheckClass,自動載入的過程開始前觸發,當返回布爾假可以停止活動操作。
  • pathFound,當一個類裝入器定位觸發
  • afterCheckClass,自動載入的過程完成後觸發。

8. 註意事項(Troubleshooting)

  1. 自動載入區分大小寫。
  2. 命名空間或首碼的方式要比文件夾的方式要快得多。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 指針是某個變數的地址,是一個地址。指針變數是存放指針(某個變數地址)的變數,是一個變數。指針變數是一個變數,也有它自己的地址;這幾句話對理解指針非常有幫助。舉例:int c = 76;int *pointer = &c;普通變數 c 和 指針變數 pointer 在記憶體中的形式如下圖:;指針變數po...
  • 1.首先來幾個英文縮寫的含義 javaSE 標準版javaEE 企業版 javaME 微型版 sdk:soft developement kit,開發工具包,包含jdk jdk:java developement kit jre:java runtime environment jvm...
  • 是的,這篇blogs是一個總結篇,最開始的時候我提到過,對於java容器或集合的學習也可以看做是對數據結構的學習與應用。在前面我們分析了很多的java容器,也接觸了好多種常用的數據結構,今天我們就來總結下這些內容。 下麵我們以數據結構的維度來總結下,在Java集合的實現過程中,底層到底使用了哪...
  • 今天,Alice 和 Bob 兩個人發明瞭一個新的取石子游戲。我們將 n 枚石子擺放成一行,從左到右每枚石子有兩個參數,能量ei和得分ai。Alice 和 Bob 兩人輪流決策,從左到右依次取石子,Alice 先手。每個回合,玩家可以選擇下列兩個操作之一:1. 消耗一個單位的能量,跳過這個回合。2....
  • 「C語言」原碼反碼補碼與位運算
  • 學過C語言的小猿們都知道,C語言中有很多的運算符:賦值運算符、算術運算符、邏輯運算符、關係運算符、條件運算符、逗號運算符、位運算符…… 運算符在代碼中發揮著極其重要的作用,Swift中也有很多的運算符,大部分與C中的運算符相似甚至相同,但也有一些改動和補充,接下來就簡單介紹一下這些與 'C...
  • int WINAPI WinMain(HINSTANCE HInstance,HINSTANCE HPreInstance,LPSTR szCmdLine,intCmdShown){MassageBox(NULL,TEXT("你好"),TEXT("window程式"),MB_OK);}hInstan...
  • 先上利於理解的代碼: 1 #coding:utf-8 2 def consumer(): 3 c_r = '' 4 while 1: 5 m = yield c_r 6 if not m: 7 return 8 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...