My question is $b the same as $a in the output? Am I just passing a reference to $a when using ($b = $a) and not making a copy of the object?
$a = new DateTime('2014-01-15');
$i = new DateInterval('P1D');
print $a->format('Y-m-d') . PHP_EOL; // 2014-01-15
$b = $a;
print $a->add($i)->format('Y-m-d') . PHP_EOL; // 2014-01-16
print $b->format('Y-m-d') . PHP_EOL; // 2014-01-16
Note the use of clone:
$a = new DateTime('2014-01-15');
$i = new DateInterval('P1D');
print $a->format('Y-m-d') . PHP_EOL; // 2014-01-15
$b = clone $a; // Here we clone the object
print $a->add($i)->format('Y-m-d') . PHP_EOL; // 2014-01-16
print $b->format('Y-m-d') . PHP_EOL; // 2014-01-15
Further explanation from the docs: if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy. It sounds like just setting $a = $b will have the same initialization of the object, meaning if one changes the other does. The variable $b becomes a sort of symbolic link to the initialized object held in $a.
Related
I've been reading about memory management in PHP and learned that variables in PHP copy the reference to zvals as long as you don't do a write operation (copy on write paradigm).
https://www.phpinternalsbook.com/php5/zvals/memory_management.html#reference-counting-and-copy-on-write
However, it does not describe what happens when you reassign a value to an already copied zval.
Here's what the book says:
$a = 1; // $a = zval_1(value=1, refcount=1)
$b = $a; // $a = $b = zval_1(value=1, refcount=2)
$c = $b; // $a = $b = $c = zval_1(value=1, refcount=3)
$a++; // $b = $c = zval_1(value=1, refcount=2)
// $a = zval_2(value=2, refcount=1)
Now, if you do another $a++, will it change the value in zval,
$a++; // $a = zval_2(value=3, refcount=1)
or will it create a new zval once again?
$a++; // $a = zval_3(value=3, refcount=1)
Following the logic of the PHP Language Reference, I guess it should be more likely option #1 as long as refcount = 1 (you would not manipulate another variable).
I want to create dynamic object property as variable in php.
For example
$b = '';
if($b != '') $b = "->b";
$a = new stdClass();
$a. $b->c;
My Target Output is
If(b == '') $a->c;
else $a->b->c;
For $b->c to work, you have to make $b an object of stdClass class. But since you made $b as a string using $b = "->b";, the former statement $b->c would throw error.
So the workaround is - make b as a property of object $a and assign an object of class stdClass to this member property. The following block of code would make this concept more clearer.
$b = '';
$a = new stdClass();
if($b != ''){
$a->b = new stdClass();
$a->b->c = 'something';
}else{
$a->c = 'something else';
}
Later, you can have the desired target output like this:
if($b == '') echo $a->c;
else echo $a->b->c;
In PHP How it differs when I create cloned object in a variable and new object created using a variable with the same class
For example
$a = new classA();
$b = clone $a;
$c = new classA();
What is the difference between $b and $c ?
You should look at the following example
<?php
class classA {
public $x=0;
}
$a = new classA();
$a->x = 20;
echo $a->x."<br />";
$b = clone $a;
$a->x = 30;
echo $a->x."<br />";
echo $b->x."<br />"; // 20 because x was 20 before cloning $a to $b
$a->x = 50;
echo $a->x."<br />"; // changed to 50
echo $b->x."<br />"; // stil 20, $a
$c = new classA();
echo $c->x;
Using cloning make, you have property x in object $b the same as in object $a because cloning simple copies object. And when creating new object, you will have new object and property value will be 0.
Cloning is simple copying object because by default for objects:
$a = $b;
PHP won't do copying (as for simple types) but will point to exact place in memory.
So for simple types you use:
$a = 5;
$b = $a;
if you want to make a copy, but for objects you need to use clone:
$a = new classA();
$a->x = 20;
$b = clone $a;
to have the same effect.
You should look in manual at Object and references and Cloning to understand those things.
I am trying to understand this article "PHP Manual -> Features -> Garbage Collection"
unfortunately few things are unclear for me.
1.
To avoid having to call the checking of garbage cycles with every
possible decrease of a refcount, the algorithm instead puts all
possible roots (zvals) in the "root buffer".
but what in case
<?php
$a = new \stdClass(); (1)
$a = new \stdClass();
Then I guess the first object become "lost" zval like
no_symbol : (refcount=1, is_ref=1) = stdObject
Will such "lost" zvals be added into root buffer or not? There is no handler for them.
2.
Variables created in function scope, what happened with them?
Ex:
<?php
function test($a = 'abc') {
$c = 123;
return 1;
}
test();
echo 'end';
What happened with $a and $c when gc starts?
These variables still have refcount set to 1.
Will they still be removed? if yes then why and how (what is happening under the cover?)
3.
How can it help for cyclic references?
Ex
<?php
$a = array('abc');
$a[] =& $a;
unset($a);
where
(refcount=1, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='abc',
1 => (refcount=1, is_ref=1)=...
)
1) The original object is replaced with the new one, and thus memory is freed instantly.
echo memory_get_usage().'<br/>';
$a = new stdClass();
echo memory_get_usage().'<br/>';
$a = new stdClass();
echo memory_get_usage().'<br/>';
2) They are gc'ed the second the function completes executing:
echo memory_get_usage().'<br/>';
function test($a = 'abc') {
$c = 123;
return 1;
}
echo memory_get_usage().'<br/>';
test();
echo memory_get_usage().'<br/>';
3) unsetting $a will leave the referenced variable in memory. You need to set the value to NULL first, and then unset.
echo memory_get_usage().'<br/>';
$a = array('abc');
echo memory_get_usage().'<br/>';
$a[] =& $a;
echo memory_get_usage().'<br/>';
$a = null;
unset($a);
echo memory_get_usage().'<br/>';
I am from Java Background. I have used objects as Call by Value and Reference in Java.
But When I am using these things in PHP i didnt achieve the my expected Result.
<?php
class A {
public $t;
function __construct() {
$this->t = 100;
}
}
/*By value */
echo 'By Value<br/>';
$obj1 = new A();
echo $obj1->t;
$obj2 = $obj1;
$obj2->t = 200;
echo $obj2->t;
echo $obj1->t; //expects Result 100 but it prints 200
/*By Reference */
echo '<br/>By Reference<br/>';
$obj3 = new A();
echo $obj3->t;
$obj4 = &$obj3;
echo $obj4->t;
$obj4->t = 500;
echo $obj4->t;
echo $obj3->t;
?>
When I am assigning one object to another one Object by value, If i modify the value of Property in Copied Object means, this will be affected Original Object too.
Plz Clear my doubt anyone...
Thanks...
Humm...PHP support both By Value and By Reference. However, there are a few quirks...
By default, PHP5 always assigns / passes objects by reference:
$obj1 = new stdClass();
$obj2 = $obj1;
print spl_object_hash($obj1);
print "<br>";
print spl_object_hash($obj2);
Output:
000000001ef37c150000000046e30ead
000000001ef37c150000000046e30ead
Basically, both $obj1 and $obj2 are pointers to the same object.
However, this is not true for primitive types (such as integer, string, etc...)
$var1 = "some string";
$var2 = $var1;
$var1 = "foo";
print $var1;
print '<br>';
print $var2;
Output:
foo
some string
Using & you can pass by reference primitives too.
$var1 = "some string";
$var2 = &$var1;
$var1 = "foo";
print $var1;
print '<br>';
print $var2;
Output:
foo
foo
And you can pass objects by value too
$obj1 = new stdClass();
$obj2 = clone $obj1;
print spl_object_hash($obj1);
print "<br>";
print spl_object_hash($obj2);
output:
0000000062516daa000000001745e928
0000000062516da9000000001745e928
In Short, by default primitive types are passed by value while objects are passed by reference.