- Php variable variables this
- PHP RFC: Fix inconsistent behavior of $this variable
- Proposal
- Disable using $this as parameter
- Disable using $this as static variable
- Disable using $this as global variable
- Disable using $this as catch variable
- Disable using $this as foreach value variable
- Disable ability to unset() $this
- Disable ability to re-assign $this indirectly through $$
- Disable ability to re-assign $this indirectly through reference
- Disable ability to re-assign $this indirectly through extract() and parse_str()
- get_defined_vars() always doesn’t show value of variable $this
- Always show true $this value in magic method __call()
- Using $this when not in object context
- Backward Incompatible Changes
- PHP $this Keyword
- Using self for static Class Members
- Difference between PHP self and this
Php variable variables this
It may be worth specifically noting, if variable names follow some kind of «template,» they can be referenced like this:
// Given these variables .
$nameTypes = array( «first» , «last» , «company» );
$name_first = «John» ;
$name_last = «Doe» ;
$name_company = «PHP.net» ;
// Then this loop is .
foreach( $nameTypes as $type )
print $ < "name_ $type " >. «\n» ;
// . equivalent to this print statement.
print » $name_first \n $name_last \n $name_company \n» ;
?>
This is apparent from the notes others have left, but is not explicitly stated.
In addition, it is possible to use associative array to secure name of variables available to be used within a function (or class / not tested).
This way the variable variable feature is useful to validate variables; define, output and manage only within the function that receives as parameter
an associative array :
array(‘index’=>’value’,’index’=>’value’);
index = reference to variable to be used within function
value = name of the variable to be used within function
$vars = [ ‘id’ => ‘user_id’ , ’email’ => ‘user_email’ ];
function validateVarsFunction ( $vars )
//$vars[‘id’]=34; // define allowed variables
$user_id = 21 ;
$user_email = ’email@mail.com’ ;
echo $vars [ ‘id’ ]; // prints name of variable: user_id
echo $< $vars [ 'id' ]>; // prints 21
echo ‘Email: ‘ .$< $vars [ 'email' ]>; // print email@mail.com
// we don’t have the name of the variables before declaring them inside the function
>
?>
The feature of variable variable names is welcome, but it should be avoided when possible. Modern IDE software fails to interpret such variables correctly, regular find/replace also fails. It’s a kind of magic 🙂 This may really make it hard to refactor code. Imagine you want to rename variable $username to $userName and try to find all occurrences of $username in code by checking «$userName». You may easily omit:
$a = ‘username’;
echo $$a;
If you want to use a variable value in part of the name of a variable variable (not the whole name itself), you can do like the following:
$price_for_monday = 10 ;
$price_for_tuesday = 20 ;
$price_for_wednesday = 30 ;
$price_for_today = $< 'price_for_' . $today >;
echo $price_for_today ; // will return 20
?>
PHP actually supports invoking a new instance of a class using a variable class name since at least version 5.2
class Foo public function hello () echo ‘Hello world!’ ;
>
>
$my_foo = ‘Foo’ ;
$a = new $my_foo ();
$a -> hello (); //prints ‘Hello world!’
?>
Additionally, you can access static methods and properties using variable class names, but only since PHP 5.3
class Foo public static function hello () echo ‘Hello world!’ ;
>
>
$my_foo = ‘Foo’ ;
$my_foo :: hello (); //prints ‘Hello world!’
?>
You may think of using variable variables to dynamically generate variables from an array, by doing something similar to: —
foreach ( $array as $key => $value )
$ $key = $value ;
>
?>
This however would be reinventing the wheel when you can simply use:
extract ( $array , EXTR_OVERWRITE );
?>
Note that this will overwrite the contents of variables that already exist.
Extract has useful functionality to prevent this, or you may group the variables by using prefixes too, so you could use: —
$array =array( «one» => «First Value» ,
«two» => «2nd Value» ,
«three» => «8»
);
extract ( $array , EXTR_PREFIX_ALL , «my_prefix_» );
?>
This would create variables: —
$my_prefix_one
$my_prefix_two
$my_prefix_three
containing: —
«First Value», «2nd Value» and «8» respectively
Another use for this feature in PHP is dynamic parsing..
Due to the rather odd structure of an input string I am currently parsing, I must have a reference for each particular object instantiation in the order which they were created. In addition, because of the syntax of the input string, elements of the previous object creation are required for the current one.
Normally, you won’t need something this convolute. In this example, I needed to load an array with dynamically named objects — (yes, this has some basic Object Oriented programming, please bare with me..)
// this is only a skeletal example, of course.
$object_array = array();
// assume the $input array has tokens for parsing.
foreach ( $input_array as $key => $value ) <
// test to ensure the $value is what we need.
$obj = «obj» . $key ;
$ $obj = new Obj ( $value , $other_var );
Array_Push ( $object_array , $ $obj );
// etc..
>
?>
Now, we can use basic array manipulation to get these objects out in the particular order we need, and the objects no longer are dependant on the previous ones.
I haven’t fully tested the implimentation of the objects. The scope of a variable-variable’s object attributes (get all that?) is a little tough to crack. Regardless, this is another example of the manner in which the var-vars can be used with precision where tedious, extra hard-coding is the only alternative.
Then, we can easily pull everything back out again using a basic array function: foreach.
//.
foreach( $array as $key => $object )
echo $key . » — » . $object -> print_fcn (). »
\n» ;
?>
Through this, we can pull a dynamically named object out of the array it was stored in without actually knowing its name.
PHP RFC: Fix inconsistent behavior of $this variable
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.
PHP $this Keyword
If you are following this tutorial from the beginning or you started from the OOPS concepts, you must have noticed the usage of $this in some of the code snippets.
this keyword is used inside a class, generally withing the member functions to access non-static members of a class(variables or functions) for the current object.
Let’s take an example to understand the usage of $this .
name = $name; > // public function to get value of name (getter method) public function getName() < return $this->name; > > // creating class object $john = new Person(); // calling the public function to set fname $john->setName("John Wick"); // getting the value of the name variable echo "My name is " . $john->getName(); ?>
In the program above, we have created a private variable in the class with name $name and we have two public methods setName() and getName() to assign a new value to $name variable and to get its value respectively.
Whenever we want to call any variable of class from inside a member function, we use $this to point to the current object which holds the variable.
We can also use $this to call one member function of a class inside another member function.
NOTE: If there is any static member function or variable in the class, we cannot refer it using the $this .
Using self for static Class Members
Instead of $this , for static class members(variables or functions), we use self , along with scope resolution operator :: . Let’s take an example,
Difference between PHP self and this
Let’s understand a few differences between self and this :
self | this |
---|---|
self keyword is not preceded by any symbol. | this keyword should be preceded with a $ symbol. |
To access class variables and methods using the self keyword, we use the scope resolution operator :: | In case of this operator, we use the —< symbol. |
It is used to refer the static members of the class. | It is used to access non-static members of the class. |
PHP self refers to the class members, but not for any particular object. This is because the static members(variables or functions) are class members shared by all the objecxts of the class. | Whereas, $this wil refer the member variables and function for a particular instance. |
Let’s take a code example to understand this better:
name; > // public function to get job description public function getDesc() < return $this->desc; > // static function to get the company name public static function getCompany() < return self::$company; >// non-static function to get the company name public function getCompany_nonStatic() < return self::getCompany(); >> $objJob = new Job(); // setting values to non-static variables $objJob->name = "Data Scientist"; $objJob->desc = "You must know Data Science"; /* setting value for static variable. done using the class name */ Job::$company = "Studytonight"; // calling the methods echo "Job Name: " .$objJob->getName()."
"; echo "Job Description: " .$objJob->getDesc()."
"; echo "Company Name: " .Job::getCompany_nonStatic(); ?>
Job Name: Data Scientist Job Description: You must know Data Science Company Name: Studytonight
In the code snippet above we have a few non-static variables and one static variable.
Because the static members are associated with class itself and not the objects of the class, hence we call them using the class name.
Also, a static member function can use a static variable inside it, while if a non-static method use a static variable inside it, then it is also called using the class name, just like a static method.