This is an old revision of the document!
PHP RFC: Remove PHP 4 Constructors
- Version: 1.0
- Date: 2014-11-17
- Author: Levi Morrison levim@php.net
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/remove_php4_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
This RFC proposes changes for two PHP versions:
- PHP 5.7: an
E_DEPRECATED
notice will be raised whenever a PHP 4 style constructor is defined. Note that this means it will not raise an error in a context where a method shares the same name as the class but is not recognized as a constructor, such as in namespaced classes or in traits. Emitting thisE_DEPRECATED
warning will help migration from PHP 5 to PHP 7. Note that the RFC to remove multiple default statements from switch blocks proposed this same technique. - PHP 7.0: methods with the same name as the class they are defined will not be recognized as constructors in any context; they will be treated as normal methods.
Some code samples in the Examples section show how code is impacted.
Backward Incompatible Changes
This RFC will break code that relies on PHP 4 constructors. The solution is to rename the constructors to __construct
. This will allow the class to be compatible with PHP 5, but breaks compatibility with PHP 4 completely.
Examples
class Filter { // PHP 5.X: filter is a constructor // PHP 5.7: filter is a constructor and an E_DEPRECATED is raised // PHP 7.0: No errror is raised; filter is a normal method and not a constructor function filter($a) {} } $filter = new ReflectionMethod('Filter', 'filter'); // PHP 5.X: bool(true) // PHP 7.0: bool(false) var_dump($filter->isConstructor());
// function filter is not used as constructor in PHP 5+ class Filter { // PHP 5.0-5.6: E_STRICT "Redefining already defined constructor" // PHP 5.7: No errror is raised // PHP 7.0: No errror 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 errror is raised // PHP 5.7: No errror is raised // PHP 7.0: No errror is raised function filter($a) {} }
<PHP> class Filter {
function filter() {}
}
class FilterX extends Filter {
function __construct() {
// PHP 5.X: Filter::filter is called; no error // PHP 7.0: "Fatal error: Cannot call constructor" // This happens because Filter no longer has a constructor // An (in draft) RFC proposal to allow this to always succeed: https://wiki.php.net/rfc/default_ctor parent::__construct(); }
}
new FilterX(); </PHP
Impact to Opcache
Opcache is likely to be unaffected by this proposal, but this has not yet been verified.
Open Issues
There are some tests that rely on behavior that this RFC would remove to trigger error conditions1). These tests would need to find a different error trigger.
Documentation should remove unnecessary cognitive load for new learners, but preserve enough information for people searching for the old behavior.
Voting
This RFC targets PHP 7 and PHP 5.7:
PHP 5.7: Raise E_DEPRECATED
whenever a PHP 4 style constructor is defined, noting that it will be a normal method in PHP 7
PHP 7.0: Stop recognizing methods with the same name as the class they are defined in as constructors.
This RFC requires 2/3 vote in favor of removing PHP 4 style constructors to pass.
Patches and Tests
A partial implementation based on the master branch can be found here: https://github.com/php/php-src/pull/901
The tests for this behavior have not yet been fixed. As mentioned in Open Issues, there are some tests that rely on an E_STRICT being generated to test other behavior; these will need to find a new trigger.
References
TODO: dig up pains caused by PHP 4 constructors in PHP 5
Links to external references, discussions or RFCs