I can see why
$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] = 37;
echo $a['ID']."\n";
echo $b."\n";
echo $c['ID']."\n";
outputs 37, 42, 37
while
$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$b = 37;
echo $a['ID']."\n";
echo $b."\n";
echo $c['ID']."\n";
outputs 37, 37, 37
In both cases $b
is a reference to $a['ID']
while $c
is a pointer to the same object as $a
.
When $b
changes $a['ID']
and $c['ID']
change because assigning $b
changes the value referenced by $a['ID']
.
When $c['ID']
changes, a new int is assigned to $a['ID']
, $b
doesn't reference $a['ID']
anymore.
But this itches me
$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] &= 0;
$c['ID'] |= 37;
echo $a['ID']."\n";
echo $b."\n";
echo $c['ID']."\n";
(outputs 37, 37, 37)
Is this defined behaviour? I didn't see anything about that in the documentation...
Let's take this code as a basis: ( refcounting documentation )
$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
This gives:
a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=2, is_ref=1),int 42
b:
(refcount=2, is_ref=1),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=2, is_ref=1),int 42
As you say:
$a
is an object, $b
is a reference of $a['ID']
( $a['ID']
and $b
: refcount=2, is_ref=1
)
and $c is copy as a reference (since PHP5), so $c is a reference of $a ( it's now the same object : refcount=2, is_ref=0
)
If we do: $c['ID'] = 37;
We get:
a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=1, is_ref=0),int 37
b:
(refcount=1, is_ref=0),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=1, is_ref=0),int 37
$c['ID']
is assigned a new int
so =>
$b
becomes independent (refcount=1
and is_ref=0
), as well as $a['ID']
and $c['ID']
BUT as $c
and $a
are dependent, $a['ID']
and $c['ID']
take the same value 37.
Now, let's take the base code and we do: $c['ID'] &= 0;
UPDATE: Unexpectedly, we get:
a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=2, is_ref=1),int 0
b:
(refcount=2, is_ref=1),int 0
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=2, is_ref=1),int 0
instead of: ( if: $c['ID'] = $c['ID'] & 0;
)
a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=1, is_ref=0),int 0
b:
(refcount=1, is_ref=0),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
public 'ID' => (refcount=1, is_ref=0),int 0
ArrayObject implements ArrayAccess so:
As said in the comment and documented here:
A direct modification is one that replaces completely the value of the array dimension, as in $obj[6] = 7. An indirect modification, on the other hand, only changes part of the dimension, or attempts to assign the dimension by reference to another variable, as in $obj[6][7] = 7 or $var =& $obj[6]. Increments with ++ and decrements with -- are also implemented in a way that requires indirect modification.
A possible answer:
"Combined Operator (+=, -=, &=, |=) could be worked as the same manner (indirect modification.)":
refcount
andis_ref
are not impacted therefore (in our case) the values of all related variables are modified. ($c['ID']
=>$a['ID']
=>$b)