levim

Levi Morrison

Contents

PHP RFC: Remove PHP 4 Constructors

Introduction

PHP 4 constructors are methods that have the same name as the class they are defined in. PHP 5 preserved the ability to use PHP 4 style constructors in some cases; the strangeness of when the constructor is and isn't used increases the mental model for programmers.

class Filter {
 
    // A constructor in PHP 4 and 5
    function filter($a) {}
}
// Namespaced classes do not recognize PHP 4 constructors
namespace NS;
class Filter {
 
    // Not a constructor
    function filter($a) {}
}
// Defining __construct and filter makes filter a normal method
class Filter {
    function __construct() {}
 
    // Not a constructor
    function filter($a) {}
}
 
//But defining filter first raises an E_STRICT
class Filter {
 
    // Not a constructor…
    function filter($a) {}
 
    // This raises E_STRICT
    function __construct() {}
}

Proposal

PHP 7 will emit E_DEPRECATED whenever a PHP 4 constructor is defined. When the method name matches the class name, the class is not in a namespace, and a PHP 5 constructor (__construct) is not present then an E_DEPRECATED will be emitted. PHP 8 will stop emitting E_DEPRECATED and the methods will not be recognized as constructors.

PHP 7 will also stop emitting E_STRICT when a method with the same name as the class is present as well as __construct.

Refer to the Examples section to see how code is impacted.

Backward Incompatible Changes

Since an E_DEPRECATED will be emitted in PHP 7 there may be some backwards compatibility breaks when people use custom error handlers.

In PHP 8 recognition for old constructors will be outright removed, meaning that anything without a __construct will not work the same way it used to. The old-style constructor will be considered a normal method and will not be called when the object is constructed. The fix is to rename the constructor to __construct.

Examples

class Filter {
 
    // PHP 5: filter is a constructor
    // PHP 7: filter is a constructor and E_DEPRECATED is raised
    // PHP 8: filter is a normal method and is not a constructor; no E_DEPRECATED is raised
    function filter($a) {}
}
 
$filter = new ReflectionMethod('Filter', 'filter');
 
// PHP 5: bool(true)
// PHP 7: bool(true)
// PHP 8: bool(false)
var_dump($filter->isConstructor());
// function filter is not used as constructor in PHP 5+
class Filter {
    // PHP 5: E_STRICT "Redefining already defined constructor"
    // PHP 7: No error is raised
    // PHP 8: No error is raised
    function filter($a) {}
    function __construct() {}
}
// function filter is not used as constructor in PHP 5+
class Filter {
    function __construct() {}
 
    // PHP 5.0.0 - 5.2.13, 5.3.0 - 5.3.2: E_STRICT "Redefining already defined constructor"
    // PHP 5.2.14 - 5.2.17, 5.3.3 - 5.6: No error is raised
    // PHP 7: No error is raised
    // PHP 8: No error is raised
    function filter($a) {}
}
class Filter {
    // PHP 5: filter is a constructor
    // PHP 7: filter is a constructor and E_DEPRECATED is raised
    // PHP 8: filter is a normal method and is not a constructor; no E_DEPRECATED is raised
    function filter() {}
}
 
class FilterX extends Filter {
 
    function __construct() {
        // PHP 5: Filter::filter is called; no error
        // PHP 7: Filter::filter is called; no error
        // PHP 8: "Fatal error: Cannot call constructor"
        parent::__construct();
    }
 
}
 
new FilterX();

Patches and Tests

An implementation based on the master branch can be found here: https://github.com/php/php-src/pull/1061

Votes

An option needs 2/3 votes to win

remove_php4_constructors (92.6% approved)
User Vote
ab No
aharvey Yes
ajf Yes
brandon Yes
bwoebi Yes
crodas Yes
daverandom Yes
davey Yes
diegopires Yes
dm Yes
dmitry Yes
dragoonis Yes
frozenfire Yes
galvao Yes
guilhermeblanco Yes
indeyets Yes
jedibc Yes
jgmdev Yes
jpauli Yes
jwage Yes
kalle Yes
kinncj Yes
krakjoe Yes
laruence No
lcobucci Yes
leigh Yes
levim Yes
lstrojny Yes
mariuz Yes
mbeccati Yes
mfonda Yes
mike Yes
mrook Yes
nikic Yes
olemarkus Yes
pajoye Yes
patrickallaert Yes
pauloelr Yes
peehaa Yes
philstu Yes
ralphschindler Yes
rdlowrey Yes
rdohms Yes
remi No
salathe Yes
santiagolizardo Yes
sobak Yes
stas No
thekid Yes
treffynnon Yes
tyrael Yes
yohgaki Yes
yunosh Yes
zeev Yes