new一個class時不需要寫require。 PHP 5.2 新增自動加載的魔術方法__autoload($class_name)
一、__autoload()的使用
__autoload.php1 2 3 4 5 6 7 8 | $db = new DB(); Height::test(); //也是支持静态方法直接调用的 function __autoload( $className ) { require $className . '.php' ; } |
1 2 3 4 5 6 7 | class DB { public function __construct() { echo 'Hello DB' ; } } |
1 2 3 4 5 6 7 8 9 10 11 | class Height { public function __construct() { echo 'Hello Height' ; } public static function test(){ echo 'Hello Height test' ; } } |
二、spl_autoload_register 使用
__autoload()不允許加載不同路徑的文件,因為一個項目中只能有一個__autoload()。因此spl_autoload_register()誕生。當我們new一個找不到的class時,PHP會自動調用spl_autoload_register註冊的函數1 2 3 4 5 6 7 8 9 10 11 | class autoloading{ //必须是静态方法,不然报错 public static function load( $className ) { require $className . '.php' ; } } //2种方法都可以 spl_autoload_register( array ( 'autoloading' , 'load' )); // spl_autoload_register('autoloading::load'); $db = new DB(); //会自动找到 |
三、多个spl_autoload_register的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | function load1( $className ) { echo 1; if ( is_file ( $className . '.php' )) { require $className . '.php' ; } } function load2( $className ) { echo 2; if ( is_file ( './app/' . $className . '.php' )) { require './app/' . $className . '.php' ; } } function __autoload( $className ) { echo 3; if ( is_file ( './lib/' . $className . '.php' )) { require './lib/' . $className . '.php' ; } } //注册了3个 spl_autoload_register( 'load1' ); spl_autoload_register( 'load2' ); spl_autoload_register( '__autoload' ); $db = new DB(); //DB就在本目录下 $info = new LibInfo(); //LibInfo 在/lib/LibInfo.php var_dump(spl_autoload_functions()); |
輸出:
1 2 3 4 5 6 7 8 9 10 | 1 Hello DB 1 2 3 Hello LibInfo array (size=3) 0 => string 'load1' (length=5) 1 => string 'load2' (length=5) 2 => string '__autoload' (length=10) |
使用spl_autoload_functions() 來查一共註冊了多少個自動加載
spl_autoload_register()使用時,__autoload()會無效,必須重新註冊進來才有效
四、spl_autoload_register自動加載+namespace命名空間
根據 PSR-0 的規範,使用namespace就能找到詳細的路徑,從而找到class文件spl_autoload_register_namespace.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //定义当前的目录绝对路径 define( 'DIR' , dirname( __FILE__ )); //加载这个文件 require DIR . '/loading.php' ; //采用`命名空间`的方式注册。php 5.3 加入的 //也必须是得是static静态方法调用,然后就像加载namespace的方式调用,注意:不能使用use spl_autoload_register( "\\AutoLoading\\loading::autoload" ); $oMySQL = new Libary\Db\MySQL(); $oMySQL ->bear(); // 调用2个namespace类 //定位到Libary目录下的Name.php Libary\Name::test(); //定位到App目录下Android目录下的Name.php App\Android\Name::test(); |
loading.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | namespace AutoLoading; class loading { public static function autoload( $className ) { //根据PSR-O的第4点 把 \ 转换层(目录风格符) DIRECTORY_SEPARATOR , //便于兼容Linux文件找。Windows 下(/ 和 \)是通用的 //由于namspace 很规格,所以直接很快就能找到 $fileName = str_replace ( '\\' , DIRECTORY_SEPARATOR, DIR . '\\' . $className ) . '.php' ; if ( is_file ( $fileName )) { require $fileName ; } else { echo $fileName . ' is not exist' ; die ; } } } |
Libary/Db/MySQL.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | namespace Libary\Db; use Libary\Name; // use放這 class MySQL { public function __construct() { echo __NAMESPACE__ . "" ; } public static function test() { echo __NAMESPACE__ . ' static function test ' ; } public function bear(){ Name::getInstance(); // 呼叫 Libary/Name.php 的 static function getInstance() } } |
Libary/Name.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | namespace Libary; use Libary\Db\MySQL; // use放在這 class Name { public function __construct() { echo __NAMESPACE__ . "" ; } public static function test() { // $oMySQL = new Libary\Db\MySQL(); // D:\bear\www\test\autoload\Libary\Libary\Db\MySQL.php is not exist // $oMySQL = new Db\MySQL(); // OK // use Libary\Db\MySQL; // Parse error: syntax error, unexpected 'use' (T_USE) $oMySQL = new MySQL(); // 打印第二個 Libary\Db echo __NAMESPACE__ . ' static function test ' ; } public static function getInstance(){ echo __NAMESPACE__ . ":getInstance" ; } } |
App/Android/Name.php
1 2 3 4 5 6 7 8 9 10 11 12 | namespace App\Android; class Name { public function __construct() { echo __NAMESPACE__ . "" ; } public static function test() { echo __NAMESPACE__ . ' static function test ' ; } } |
輸出:
1 2 3 4 5 | Libary\Db Libary:getInstance Libary\Db Libary static function test App\Android static function test |
s
...using __autoload() is discouraged and may be deprecated or removed in the future.
使用 __autoload() 是將會被棄用的(PHP 7.2.0),因為只能使用一次。應使用spl_autoload_register()
use Libary\Db\MySQL; // use 使用絕對路徑,放在class外面,namespace後面
參考資料:
https://www.zybuluo.com/phper/note/66447 PHP中的自动加载
https://stackoverflow.com/questions/12702527/how-to-call-autoload-in-php-code How to call __autoload() in php code
https://stackoverflow.com/questions/33342994/unexpected-use-t-use-when-trying-to-use-composer unexpected 'use' (T_USE)
https://www.php-fig.org/psr/psr-0/ PSR-0: Autoloading Standard
沒有留言:
張貼留言