100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > php自动加载原理 php中的自动加载类机制原理

php自动加载原理 php中的自动加载类机制原理

时间:2023-09-09 19:05:29

相关推荐

php自动加载原理 php中的自动加载类机制原理

PHP最早讀取套件的方法

初學PHP時,最早會面對的問題之一就是require與include差別何在?

require_once與include_once又是什麼?

弄懂這些問題之後,如果不使用framework,直接開發,便常出現類似這樣的code:

// whatever.php

// 這檔案需要用到幾個類別

require 'xxx_class.php';

require 'yyy_class.php';

require 'zzz_class.php';

// ...

然後在其他檔案會出現:

// another.php

// 這檔案需要用到幾個類別

require 'yyy_class.php';

require 'zzz_class.php';

// ...

這樣的結果,會產生至少兩個問題:

1. 許多檔案用到同樣幾個class,於是在不同地方都需要載入一次。

2. 當類別多了起來,會顯得很亂、忘記載入時還會出現error。

那麼,不如試試一種懶惰的作法?

寫一個php,負責載入所有類別:

// load_everything.php

require 'xxx_class.php';

require 'yyy_class.php';

require 'zzz_class.php';

require 'aaa_class.php';

require 'bbb_class.php';

require 'ccc_class.php';

然後在其他檔案都載入這支檔案即可:

require 'load_everything.php'

結果新問題又來了:當類別很多的時候,隨便一個web page都會載入一堆code,吃爆記憶體,怎麼辦呢?

__autoload

為了解決這個問題,PHP 5開始提供__autoload這種俗稱「magic method」的函式。

當你要使用的類別PHP找不到時,它會將類別名稱當成字串丟進這個函式,在PHP噴error投降之前,做最後的嘗試:

// autoload.php

function __autoload($classname) {

if ($classname === 'xxx.php'){

$filename = "./". $classname .".php";

include_once($filename);

} else if ($classname === 'yyy.php'){

$filename = "./other_library/". $classname .".php";

include_once($filename);

} else if ($classname === 'zzz.php'){

$filename = "./my_library/". $classname .".php";

include_once($filename);

}

// blah

}

也因為PHP這種「投降前最後一次嘗試」的行為,有時會讓沒注意到的人困惑「奇怪我的code怎麼跑得動?我根本沒有require啊..」,所以被稱為「magic method」。

如此一來,問題似乎解決了?

可惜還是有小缺點..,就是這個__autoload函式內容會變得很巨大。以上面的例子來說,一下會去根目錄找、一下會去other_library資料夾、一下會去my_library資料夾尋找。在整理檔案的時候,顯得有些混亂。

spl_autoload_register

於是PHP從5.1.2開始,多提供了一個函式。

可以多寫幾個autoload函式,然後註冊起來,效果跟直接使用__autoload相同。

現在可以針對不同用途的類別,分批autoload了。

spl_autoload_register('my_library_loader');

spl_autoload_register('other_library_loader');

spl_autoload_register('basic_loader');

function my_library_loader($classname) {

$filename = "./my_library/". $classname .".php";

include_once($filename);

}

function other_library_loader($classname) {

$filename = "./other_library/". $classname .".php";

include_once($filename);

}

function basic_loader($classname) {

$filename = "./". $classname .".php";

include_once($filename);

}

每個loader內容可以做很多變化。可以多寫判斷式讓它更智慧、可以進行字串處理…。

自動載入類別的問題終於解決了…。

使用spl_autoload_register注册了自定义的处理器之后,便不会再调用__autoload这个默认的处理器了。这样做的有点在于:__autoload是一个函数,它只能被定义一次,使用spl_autoload_register可以把需要在__autoload这一个加载器里做的事拆分到多个加载器中去分类管理,并且当php需要动态加载类时,spl_autoload_register会按注册顺序依次调用这些加载器来寻找并加载相应的类文件。

另外,注册到spl_autoload_register里的处理器方法还可以是类的静态方法:

class test {

public static function loadprint( $class ) {

$file = $class . '.class.php';

if (is_file($file)) {

require_once($file);

}

}

}

spl_autoload_register( array('test','loadprint') );

//另一种写法:spl_autoload_register( "test::loadprint" );

$obj = new PRINTIT();

$obj->doPrint();

?>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。