程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> Phalcon自動加載(PHP自動加載),phalcon加載php

Phalcon自動加載(PHP自動加載),phalcon加載php

編輯:關於PHP編程

Phalcon自動加載(PHP自動加載),phalcon加載php


自動加載(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至少需要做三件事(“三步走”),它們分別是:

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

因此__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:

函數說明

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();

 

具體實現:

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();

 

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

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

具體實現:

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將不再支持前綴。

具體實現:

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將在個文件夾下大量查找與類名相同的文件。在使用注冊目錄自動加載時,要注意注冊目錄的相關性,即將重要的目錄放在前面。

具體實現:

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. 下一頁:
Copyright © 程式師世界 All Rights Reserved