Php assign object to this

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 Object Assignment vs Cloning

is that in first case you assign a reference of already existing object and in second one you create a new object and assign it to the variable.

Moreover, when you use clone keyword you can use magic method __clone() which gives you better control on object cloning. From php manual:

Once the cloning is complete, if a __clone() method is defined, then the newly created object’s __clone() method will be called, to allow any necessary properties that need to be changed.

A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn’t contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

Let me give you a live example

$dateA = new \Datetime('2017-04-04'); $dateB = $dateA; // $dateB references exactly the same object as $dateA $dateB->modify('+1 day'); var_dump($dateA->format('Y-m-d')); //string(10) "2017-04-05" var_dump($dateB->format('Y-m-d')); //string(10) "2017-04-05" // $dateA is still modified by the code above so it has 2017-04-05 $dateC = clone $dateA; // we clone $dateA so it's a new object $dateC->modify('+1 day'); var_dump($dateA->format('Y-m-d')); // string(10) "2017-04-05" var_dump($dateC->format('Y-m-d')); // string(10) "2017-04-06" 

// side note for datetime I recommend using DatetimeImmutable instead of Datetime

EDIT: internal types

// create 2 integer variables $a and $b $a = 1; $b = 1; // create a new $c variable and assign the *value* of $a to that variable $c = $a; // create a new $d variable and assign a reference to $b variable $d = &$b; // increment $b, $c and $d variables $b++; $c++; $d++; echo $a; // 1 echo $b; // 3 echo $c; // 2 echo $d; // 3 

because $d references $b when we increment its value it’ll also change the value of $b.

The difference between internal objects like strings, int, float etc. is that they are passed by value and objects are passed by default via reference

Notice: You cannot use clone with internal objects.

well, basically those variables are nothing but pointers to the memory space, where object resides. If you store pointer value in another pointer, and then reset original pointer, nothing will happen to the memory area they both once pointed to.

Objects are abstract data in memory. A variable always holds a reference to this data in memory. Imagine that $foo = new Bar creates an object instance of Bar somewhere in memory, assigns it some id #42 , and $foo now holds this #42 as reference to this object. Assigning this reference to other variables by reference or normally works the same as with any other values. Many variables can hold a copy of this reference, but all point to the same object.

clone explicitly creates a copy of the object itself, not just of the reference that points to the object.

$foo = new Bar; // $foo holds a reference to an instance of Bar $bar = $foo; // $bar holds a copy of the reference to the instance of Bar $baz =& $foo; // $baz references the same reference to the instance of Bar as $foo 

Just don’t confuse «reference» as in =& with «reference» as in object identifier.

$blarg = clone $foo; // the instance of Bar that $foo referenced was copied // into a new instance of Bar and $blarg now holds a reference // to that new instance 

PHP doesn’t manage the objects the same way it manages the other data types. A string (or an integer, boolean, float or array) is directly stored in the variable. When the value of the variable is assigned to another variable, the value is copied 1 into the new variable.

$x = array('a'); $y = $x; // $x and $y are different and unrelated variables; they do not share anything $y[] = 'b'; print_r($y); // Array // ( // [0] => a // [1] => b // ) print_r($x); // Array // ( // [0] => a // ) 

How PHP handles the objects assignment?

The objects, on the other hand, are handled by PHP using unique identifiers. When an object is assigned to a variable, the identifier is stored in the variable and not the actual object.

When the value of the variable is assigned to another variable, the identifier is copied and not the object itself. This makes the two variables point to the same object.

Using your example, the values of variables $instance and $assigned are equal, they both contain the identifier of the same object. $reference , on the other side, is a reference, i.e. an alias (a different name) of variable $assigned . This is why the statement $instance = null; clears the content of variables $reference and $assigned but it doesn’t affect the variable $instance and also the object whose identifier is stored in it.

Before setting $reference to null , one can use any of $instance , $assigned or reference to access the SimpleClass object created on the first line of your example. F.e:

$instance = new SimpleClass(); $assigned = $instance; $instance->var = '$assigned will have this value'; echo($instance->var); // It prints: // $assigned will have this value // $assigned is also modified because it is the same object echo($assigned->var); // It prints: // $assigned will have this value 

Read more about PHP objects and references in the documentation.

What happens when $assigned = clone $instance ?

The clone operator creates a duplicate of its operand. It creates a new object and it initializes all its properties by assigning the values of the properties of the original object to them. This means that if the clone object contains objects as properties, these properties are duplicated by simple assignment, not by cloning. 2

After this statement, $assigned contains a different value than $instance because they store now the IDs of different objects. Being different objects, the changes of $instance do not affect $assigned any more.

$instance = new SimpleClass(); $instance->var = '$instance has this value'; $assigned = clone $instance; echo($assigned->var); // It prints: // $instance has this value $assigned->var = '$assigned has a different value'; echo($assigned->var); // It prints: // $assigned has a different value // $instance is not modified echo($instance->var); // It prints: // $instance has this value 

1 This is not entirely true. For optimization purposes, the arrays are not copied until they are modified (copy-on-write). However, this is an implementation detail and for the purpose of this discussion it is fine to consider all values except the objects are copied when they are assigned to a new variable.

2 This is also called «shallow» cloning. In order to get a «deep» clone (a real duplicate that doesn’t share anything with the original), the class of a cloned object that has objects as properties must implement the __clone() magic method and clone the properties of the original object. Also, the classes of these properties must implement __clone() and so on.

Источник

Читайте также:  Понятие об html основные теги
Оцените статью