====== PHP RFC: Fix inconsistent behavior of $this variable ======
* Version: 0.9
* Date: 2016-05-23
* Author: Dmitry Stogov, dmitry@zend.com
* Status: Accepted
* First Published at: https://wiki.php.net/rfc/this_var
===== Introduction =====
Historically PHP implementation accessed special $this variable using two different methods. In some cases this might lead to significant inconsistency, when $this accessed through different methods might have different values.
class C {
function foo() {
var_dump($this);
}
function bar() {
$a="this";
$$a=42;
var_dump($this); // prints int(42)
$this->foo(); // prints object(C)#1 (0) {}
}
}
$x = new C;
$x->bar();
This RFC proposes disabling modification of $this variable using "magic code" and make $this always behave in the same way.
===== Proposal =====
==== Disable using $this as parameter ====
The following code worked in PHP 7, but will emit compilation error in PHP 7.1
function foo($this) { // Fatal error: Cannot use $this as parameter
}
==== Disable using $this as static variable ====
The following code leaded to "Cannot re-assign $this" compilation error. In PHP 7.1 it will produce more suitable error message - "Cannot use $this as static variable".
static $this; // Fatal error: Cannot use $this as static variable
==== Disable using $this as global variable ====
The following code worked in PHP 7, but will emit compilation error in PHP 7.1
global $this; // Fatal error: Cannot use $this as global variable
==== Disable using $this as catch variable ====
The following code worked in PHP 7, but will emit compilation error in PHP 7.1
try {
...
} catch (Exception $this) { // Fatal error: Cannot re-assign $this
}
==== Disable using $this as foreach value variable ====
The following code worked in PHP 7, but will emit compilation error in PHP 7.1
foreach ($a as $this) { // Fatal error: Cannot re-assign $this
}
==== Disable ability to unset() $this ====
It's not allowed to re-assign $this, so why it should be allowed to unset() it.
The following code worked in PHP 7, but will emit compilation error in PHP 7.1
unset($this); // Fatal error: Cannot unset $this
==== Disable ability to re-assign $this indirectly through $$ ====
An attempt to re-assign $this through $$ assignment will lead to throwing of Error exception.
$a = "this";
$$a = 42; // throw new Error("Cannot re-assign $this")
It's still possible to read $this value through $$.
==== Disable ability to re-assign $this indirectly through reference ====
Indirect re-assign $this through reference won't make effect in PHP 7.1
class C {
function foo(){
$a =& $this;
$a = 42;
var_dump($this); // prints object(C)#1 (0) {}, php-7.0 printed int(42)
}
}
$x = new C;
$x->foo();
==== Disable ability to re-assign $this indirectly through extract() and parse_str() ====
Few internal PHP functions may re-assign local variable. In PHP 7.1 they cannot change value of $this variable and throw Error exception.
class C {
function foo(){
extract(["this"=>42]); // throw new Error("Cannot re-assign $this")
var_dump($this);
}
}
$x = new C;
$x->foo();
==== get_defined_vars() always doesn't show value of variable $this ====
In PHP 7.0 and below get_defined_vars() might show or not show value of $this depending on some condition. (e.g. it was shown if we used $this variable itself, but not if it was used in a $this property reference or method call). In PHP 7.1 we won't show the value of $this in all cases.
==== Always show true $this value in magic method __call() ====
In PHP 7.0 and below $this in **static** magic method __call() had value NULL. However it was possible to access properties and call object methods.
class C {
static function __call($name, $args) {
var_dump($this); // prints object(C)#1 (0) {}, php-7.0 printed NULL
$this->test(); // prints "ops"
}
function test() {
echo "ops\n";
}
}
$x = new C;
$x->foo();
==== Using $this when not in object context ====
Attempt to use $this in plain function or method now will lead to exception "Using $this when not in object context". This unifies behavior with method call and property access. Previously PHP emitted "undefined variable" notice and continued execution assuming $this is NULL. It's still possible to use isset($this) and empty($this) to check object context.
function foo() {
var_dump($this); // throws "Using $this when not in object context"
// php-7.0 emitted "Undefined variable: this" and printed NULL
}
foo();
===== Backward Incompatible Changes =====
All the BC breaks are intentional and they are described in the proposal section.
===== Proposed PHP Version(s) =====
PHP 7.1
===== RFC Impact =====
==== To SAPIs ====
none
==== To Existing Extensions ====
none
==== To Opcache ====
The proposed implementation is compatible with opcache
===== Open Issues =====
none
===== Proposed Voting Choices =====
The vote is a straight Yes/No vote, that requires a 2/3 majority.
The voting began on Jun 6 and will close on Jun 16.
* Yes
* No
===== Patches and Tests =====
[[https://github.com/php/php-src/pull/1918|PR 1918]]
===== Implementation =====
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit [[ http://git.php.net/?p=php-src.git;a=commitdiff;h=a9512af8109e889eb2c6042c57797184930667cd|a9512af8109e889eb2c6042c57797184930667cd]]
- a link to the PHP manual entry for the feature