文档章节

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

码上有春天
 码上有春天
发布于 2016/05/16 10:44
字数 843
阅读 59
收藏 1

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

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

 

码上有春天
粉丝 5
博文 82
码字总数 55985
作品 0
广州
程序员
私信 提问
加载中
请先登录后再评论。
Yii的类自动加载机制

Yii的类自动加载机制 在Yii中,所有类、接口、Traits都可以使用类的自动加载机制实现在调用前自动加载。Yii借助了PHP的类自动加载机制高效实现了类的定位、导入,这一机制兼容 PSR-4 的标准。...

echojson
2018/10/21
0
0
php之自动加载(懒加载)

有A类和B类,如果在A类实例化B类,最简单直接的方法就是在B中使用include require_once A的文件,但是这种方法显然是不友好的,在框架中叶不是这么做的,在框架中使用的是自动加载的机制也成...

osc_bm1l5rx8
2019/03/01
2
0
php autoload机制学习

在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进行复用,同时将来维护时也很便利。这也是OO设计的基本思想之一。在PHP5之前,...

babygo
2014/01/13
54
0
PHP autoload与spl_autoload自动加载机制的深入理解

(1) autoload机制概述 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进行复用,同时将来维护时也很便利。这 也是OO设计的基本...

Junn
2014/06/10
9
0
PHP autoload机制详解

PHP autoload机制详解 (1) autoload机制概述 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进行复用,同时将来维护时也很便利...

lincoln.yu
2013/07/10
995
1

没有更多内容

加载失败,请刷新页面

加载更多

CentOS6.9下手动编译并安装Python3.7

CentOS6.9默认安装的python版本为2.6.6,若想安装python3以上版本,只能手工编译安装 下面介绍python3.7.3版本的手动编译并安装的步骤 1、下载Python3.7.3的源码包 https://www.python.org/f...

yuanfan2012
2019/05/09
0
0
用canvas画太极图(一步步详解附带源代码)

canvas绘图 该元素负责在页面中设定一个区域,然后由js动态地在这个区域中绘制图形。这个技术最早是由美国苹果公司推出的,目的是为了取代flash,很快主流浏览器都支持它。 绘制路径 要绘制路...

osc_8adtko4d
59分钟前
7
0
iOS逆向开发(5):微信强制升级的突破

接下来的几篇文章,小程以微信为例,实战地演示一下:如何注入iOS的APP。其中使用到的知识,基本在前面的文章中都有介绍到。 小白:小程,我想用回旧版本的微信! 小程:为什么要用旧版本微信...

广州小程
05/21
6
0
时间格式的处理,前端的时间显示2020-07-13T16:02:00.000+0000

在后端添加@JsonFormat @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") 在这里插public class CdEqInfoVO { /** * 设备id */......

osc_ekw8urc6
今天
9
0
CLion 中的 Makefile 项目:现已公开!

CLion 2020.2 EAP2 带来了期待已久的 Makefile 项目支持。尽管它仍在初期阶段,具有各种局限性和已知问题,但足以应付大量项目。 您有 Makefile 项目吗?查看原文获取免费的 EAP 版本并立即尝...

Bennyhuo
前天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部