在面向对象中 PHP 构造方法的识别
众所周知,由于历史原因,PHP 之前是使用类名作为构造函数,在 PHP 5 中引入的新
的构造函数__construct。为了实现向后兼容性,如果 PHP 5
在类中找不到 __construct() 函
数,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。
因此唯一会产生兼容性问题的情况是:类中已有一个名为 __construct() 的方法,但
它却又不是构造函数。有如下一段代码:
1
<?php
2
class Foo {
3
4
public function Foo() {
5
6
}
7
8
private function __construct() {
9
10
}
11 }
12
13 new Foo();
14 die();
此时,输出为:
Fatal error: Call to private Foo::__construct() from invalid context
此时,PHP 识别出来的构造函数是__construct,因为是 private,于是在外部调用出错。
好吧,我们从 PHP 的 C 源码中查找一下原因吧。从 SQL 的扩展类中直接查找类的定义开
始:
15 spl_iterators.c 3228
行
REGISTER_SPL_STD_CLASS_EX(IteratorIterator,
spl_dual_it_new, spl_funcs_IteratorIterator);
16 ///spl_functions.h 31
行
17 #define REGISTER_SPL_STD_CLASS_EX(class_name, obj_ctor, funcs) \
18
spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, funcs
TSRMLS_CC);
19 //spl_functions.c 41
行
20 PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, void *
obj_ctor, const zend_function_entry * function_list TSRMLS_DC)
21
22 //spl_functions.c 2235
行
23 ZEND_API
zend_class_entry
*zend_register_internal_class(zend_class_entry
*orig_class_entry TSRMLS_DC) /* {{{ */
24 //调用 do_register_internal_class
函数
25
26 //zend_API.c 2169
行
27 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry,