As we all know, due to historical reasons, PHP previously used class names as constructors and introduced the new construct _ construct in PHP5. To implement backward compatibility, if PHP5 cannot find the _ construct () function in the class, it will try to find the old constructor, that is, a function with the same name as the class. Therefore, the only situation that causes compatibility problems "> <LINKhref =" http :/
As we all know, due to historical reasons, PHP previously used class names as constructors and introduced the new construct _ construct in PHP 5. To achieve backward compatibility, if PHP 5 cannot find the _ construct () function in the class, it will try to find the old constructor, that is, the function with the same name as the class.
Therefore, the only situation that causes compatibility problems is that the class already has a method named _ construct (), but it is not a constructor. The following code is provided:
-
- class Foo {
-
- public function Foo() {
-
- }
-
- private function __construct() {
-
- }
- }
-
- new Foo();
- die();
In this case, the output is:
Fatal error: Call to private Foo ::__ construct () from invalid context
In this case, the constructor identified by PHP is _ construct. because it is private, an error occurs during external calls. Okay. let's look for the reason from the php c source code. Start from the SQL extension class to directly find the class definition:
- Spl_iterators.c 3228 row REGISTER_SPL_STD_CLASS_EX (IteratorIterator, spl_dual_it_new, spl_funcs_IteratorIterator );
- /// Spl_functions.h 31
- # Define REGISTER_SPL_STD_CLASS_EX (class_name, obj_ctor, funcs )\
- Spl_register_std_class (& spl_ce _ # class_name, # class_name, obj_ctor, funcs TSRMLS_CC );
- // Spl_functions.c 41
- PHPAPI void spl_register_std_class (zend_class_entry ** ppce, char * class_name, void * obj_ctor, const zend_function_entry * function_list TSRMLS_DC)
- // Spl_functions.c 2235 row
- ZEND_API zend_class_entry * zend_register_internal_class (zend_class_entry * orig_class_entry TSRMLS_DC )/*{{{*/
- // Call the do_register_internal_class function
- // Zend_API.c, row 3
- Static zend_class_entry * do_register_internal_class (zend_class_entry * orig_class_entry, zend_uint ce_flags TSRMLS_DC )/*{{{*/
- // Call
- Zend_register_functions (class_entry, class_entry-> builtin_functions, & class_entry-> function_table, MODULE_PERSISTENT TSRMLS_CC );
- // Zend_API.c, row 3
- /* Look for ctor, dtor, clone
- * If it's an old-style constructor, store it only if we don't have
- * A constructor already.
- */
- If (fname_len = class_name_len )&&! Memcmp (lowercase_name, lc_class_name, class_name_len + 1 )&&! Ctor ){
- Ctor = reg_function;
- } Else if (fname_len = sizeof (ZEND_CONSTRUCTOR_FUNC_NAME)-1 )&&! Memcmp (lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof (ZEND_CONSTRUCTOR_FUNC_NAME ))){
- Ctor = reg_function;
- }
- Scope-> constructor = ctor; // Check the constructor in row 1961.
The above code is PHP 5.3.0
From the above tracking process, if _ construct (ZEND_CONSTRUCTOR_FUNC_NAME) exists when the program registers all functions, it will overwrite the class_name (class name) constructor, make it exist as a regular member function. The code is as follows:
-
- class Foo {
-
- public function Foo() {
- echo 'Foo';
- }
-
- public function __construct() {
- echo '__construct';
- }
- }
-
- $foo = new Foo();
- $foo->Foo();
For the error in the previous example, we can find the source in zend/zend_object_handlers.c 1057 line ZEND_API union _ zend_function * zend_std_get_constructor (zval * object TSRMLS_DC.