Table of 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();

Voting

This RFC targets PHP 7 and PHP 8. Please read the RFC to understand what is being proposed.

This RFC requires 2/3 vote in favor of deprecating and removing PHP 4 style constructors to pass.

Do you vote to remove PHP 4 constructors as outlined in this RFC?

remove_php4_constructors
Real name Yes No
ab (ab)  
aharvey (aharvey)  
ajf (ajf)  
brandon (brandon)  
bwoebi (bwoebi)  
crodas (crodas)  
daverandom (daverandom)  
davey (davey)  
diegopires (diegopires)  
dm (dm)  
dmitry (dmitry)  
dragoonis (dragoonis)  
frozenfire (frozenfire)  
galvao (galvao)  
guilhermeblanco (guilhermeblanco)  
indeyets (indeyets)  
jedibc (jedibc)  
jgmdev (jgmdev)  
jpauli (jpauli)  
jwage (jwage)  
kalle (kalle)  
kinncj (kinncj)  
krakjoe (krakjoe)  
laruence (laruence)  
lcobucci (lcobucci)  
leigh (leigh)  
levim (levim)  
lstrojny (lstrojny)  
mariuz (mariuz)  
mbeccati (mbeccati)  
mfonda (mfonda)  
mike (mike)  
mrook (mrook)  
nikic (nikic)  
olemarkus (olemarkus)  
pajoye (pajoye)  
patrickallaert (patrickallaert)  
pauloelr (pauloelr)  
peehaa (peehaa)  
philstu (philstu)  
ralphschindler (ralphschindler)  
rdlowrey (rdlowrey)  
rdohms (rdohms)  
remi (remi)  
salathe (salathe)  
santiagolizardo (santiagolizardo)  
sobak (sobak)  
stas (stas)  
thekid (thekid)  
treffynnon (treffynnon)  
tyrael (tyrael)  
yohgaki (yohgaki)  
yunosh (yunosh)  
zeev (zeev)  
Final result: 50 4
This poll has been closed.

Voting will close on the evening (UTC-7) of March 6th.

Patches and Tests

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