本文目的

本文简要的描述了PHP提供的autoload机制,以及在scake中使用实践。用于减少不必要的文件包含,提高php系统性能。

 

什么是__autoload

php是脚本语言,不同于c++只需要编译一次,php每次执行过程中都需要编译,所以提高php编译效率,可以提高php脚本执行速度。

每次,当你使用一个新的类时,你需要包含这个类文件,然后在new出这个类。当一个脚本中依赖了很多其他脚本中定义的类时,往往脚本的样子如下:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​/** ​


​* 文件non_autoload.php ​


​*/​​ 


 


​require_once​​​​(‘your/proj/inc/A.php’);  ​


​require_once​​​​(‘your/proj/inc/B.php’);  ​


​require_once​​​​(‘your/proj/inc/C.php’);  ​


 


​if​​ ​​(条件A) {  ​


​$a​​ ​​= ​​​​new​​ ​​A();  ​


​$b​​ ​​= ​​​​new​​ ​​B();  ​


​$c​​ ​​= ​​​​new​​ ​​C();  ​


​// … 业务逻辑  ​


​} ​​​​else​​ ​​if​​ ​​(条件B) {  ​


​$a​​ ​​= newA();  ​


​$b​​ ​​= ​​​​new​​ ​​B();  ​


​// … 业务逻辑  ​


​}​



这样就会有一个问题:如果脚本执行“条件B”这个分支时,C.php这个文件其实没有必要包含。因为,任何一个被包含的文件,无论是否使用,均会被php引擎编译。如果不使用,却被编译,这样可以被视作一种资源浪费。更进一步,如果C.php包含了D.php,D.php包含了E.php。并且大部分情况都执行“条件B”分支,那么就会浪费一部分资源去编译C.php,D.php,E.php三个“无用”的文件。

这时候,可以通过PHP的__autoload方法去除这种浪费,__autoload方法提供一种“lazy load”的机制,当第一次需要使用相关类时调用,这样就不会加载不必要的类。还是通过上面的例子,修改如下:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20




​/** ​


​* 文件autoload_demo.php ​


​*/​​ 


​function​​  ​​__autoload(​​​​$className​​​​) {  ​


​$filePath​​ ​​= “your/proj/inc/{​​​​$className​​​​}.php”;  ​


​if​​ ​​(​​​​is_readable​​​​(​​​​$filePath​​​​)) {  ​


​require​​​​(​​​​$filePath​​​​);  ​


​}  ​


​}  ​


 


​if​​ ​​(条件A) {  ​


​$a​​ ​​= ​​​​new​​ ​​A();  ​


​$b​​ ​​= ​​​​new​​ ​​B();  ​


​$c​​ ​​= ​​​​new​​ ​​C();  ​


​// … 业务逻辑  ​


​} ​​​​else​​ ​​if​​ ​​(条件B) {  ​


​$a​​ ​​= newA();  ​


​$b​​ ​​= ​​​​new​​ ​​B();  ​


​// … 业务逻辑  ​


​}​



可以看到,文件开头去掉了连串的require方法,使用了php的魔术方法__autoload替代。该函数的工作原理如下:

当php引擎第一次使用类A,但是找不到时,会自动调用__autoload方法,并将类名“A”作为参数传入。所以,我们需要的做的就是根据类名,找到对应的文件,并包含进来,如果我们的方法也找不到,那么php引擎就会报错。注意,这里可以只用require,因为一旦包含进来后,php引擎再遇到类A时,将不会调用__autoload,而是直接使用内存中的类A,不会导致多次包含。

所以,使用__autoload的关键在于,如何根据类名,找到对应类定义的文件。

 


炊烟起了;夕阳下了;细雨来了 多调试,交互式编程体验 记录,独立思考,对比 感谢转载作者 修车 国产化 read and connect 匍匐前进, 讲故事