咱們使用另外一個文件定義的一個class的時候,傳統的狀況下須要require XXX.php
php
//Good.php <?php class Good{ //...... } //use.php <?php require 'Good.php'; //包含進來文件 $good = new Good(); //如今可使用Good類
可是寫require真的很煩!!如今可使用一個自動加載函數,發現類沒有被定義的時候自動根據咱們定義的規則幫咱們去require須要的文件。git
//Good.php <?php class Good{ //...... } //use.php <?php function __autoload($className){ require $className . '.php'; //定義包含的規則 } $good = new Good(); //可使用Good類,發現沒有定義,會自動調用__autoload函數,如今'Good'做爲參數傳入了__autoload函數,去包含須要的文件
__autoload函數不能解決全部的問題,如今的項目已經很是複雜,光一個autoload函數已經不能知足須要了,由於可能不一樣的模塊使用了不一樣的自動加載規則。github
spl_autoload_register將函數註冊到SPL autoload函數隊列中,它實際上建立了 __autoload 函數的隊列
,按定義時的順序逐個執行。相比之下,__ autoload() 只能夠定義一次。web
bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
autoload_functionsql
欲註冊的自動裝載函數。若是沒有提供任何參數,則自動註冊 autoload 的默認實現函數spl_autoload()。app
throw函數
此參數設置了 autoload_function 沒法成功註冊時, spl_autoload_register()是否拋出異常。ui
prependthis
若是是 true,spl_autoload_register() 會添加函數到隊列之首,而不是隊列尾部。spa
sql_autoload_resister('load_function'); //函數名 sql_autoload_resister(array('load_object', 'load_function')); //類和靜態方法 sql_autoload_resister('load_object::load_function'); //類和方法的靜態調用 //php 5.3以後,也能夠像這樣支持匿名函數了。 spl_autoload_register(function($className){ if (is_file('./lib/' . $className . '.php')) { require './lib/' . $className . '.php'; } });
note:使用了spl_autoload_register以後原來的__autoload函數就失效了,若是須要繼續使用,須要顯示的註冊它
if (function_exists('__autoload')) { spl_autoload_register('__autoload'); } //。。。。。。 spl_autoload_register('your_autoload_function'); //如今註冊另外一個
是否繼續在自動加載函數隊列中查找不取決於加載函數的返回值和是否require了文件,只有真正require須要的文件纔會中止
//Good.php位於app文件夾下 <?php class Good{ //...... } //Another.php,位於use同級文件夾下 <?php class Another{ } //use.php <?php function load1($className) { echo "load1\n"; if (file_exists($className.'.php')) { echo 'found: '.$className.PHP_EOL; require $className; } else { echo 'not found: '.$className.PHP_EOL; } } function load2($className) { echo "load2\n"; require 'Another.php'; echo 'require another class'.PHP_EOL; return true; } function load3($className) { echo "load3\n"; if (file_exists('app/'.$className.'.php')) { echo 'found '.$className.PHP_EOL; require 'app/'.$className.'.php'; } else { echo 'not found: '.$className.PHP_EOL; } } spl_autoload_register('load1'); spl_autoload_register('load2'); spl_autoload_register('load3'); $a = new Good();
輸出以下
load1 not found: Good load2 require another class load3 found Good
可使用spl_autoload_functions()
得到註冊的全部函數
Array ( [0] => load1 [1] => load2 [2] => load3 )
取消註冊的自動加載函數spl_autoload_unregister
spl_autoload_unregister('load1');
spl_autoload()是__autoload()函數的默認實現
提供了autoload()的一個默認實現。若是不使用任何參數調用 spl_autoload_register() 函數,則之後在進行 autoload() 調用時會自動使用此函數。
完整的規範請參考PSR-4: Autoloader
標準的類名應該具備下列形式
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
須要強調的:
當根據命名空間載入文件時候:
.php
爲後綴的文件同名。完整類名 | 命名空間前綴 | 文件基目錄 | 文件路徑 |
---|---|---|---|
\Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
\Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
\Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
\Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |
採用了匿名函數的方式
<?php /** * An example of a project-specific implementation. * * After registering this autoload function with SPL, the following line * would cause the function to attempt to load the \Foo\Bar\Baz\Qux class * from /path/to/project/src/Baz/Qux.php: * * new \Foo\Bar\Baz\Qux; * * @param string $class The fully-qualified class name. * @return void */ spl_autoload_register(function ($class) { // project-specific namespace prefix $prefix = 'Foo\\Bar\\'; // base directory for the namespace prefix $base_dir = __DIR__ . '/src/'; // does the class use the namespace prefix? $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // no, move to the next registered autoloader return; } // get the relative class name $relative_class = substr($class, $len); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php //下邊這一行很關鍵 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // if the file exists, require it if (file_exists($file)) { require $file; } });
參考資料: