References
A rare, yet fundamental, problem when implementing libraries for deep cloning and object graph analysis, for instance, is the reasoning about references. In the past, code that needs to detect references or reference equality had to use brittle and slow workarounds.
To remedy this situation, the ReflectionReference
class was introduced as a first-class API for the reflection of
references.
A function or method can either accept an argument by reference or by value. The way in which an argument is accepted is declared in the signature. It is impossible to determine in the body of a function or method whether an argument was originally a reference or not. Access to the structure, for instance an array or an object, that originally contained the value is required for this determination.
ReflectionReference
requires the array and the index
of the array’s value in question to be able to determine whether or
not that value holds a reference. This is why
ReflectionReference
objects are created like so:
$array = [0];
var_dump(ReflectionReference::fromArrayElement($array, 0));
$a = &$array[0];
var_dump(ReflectionReference::fromArrayElement($array, 0)->getId());
Executing the code shown above will print the output shown below:
NULL
string(20) "..."
ReflectionReference::fromArrayElement()
returns a
ReflectionReference
object if the specified array
element holds a reference. If this element does not hold a reference
then null
is returned instead of a
ReflectionReference
object.
The ReflectionReference::getId()
method returns a
string that uniquely identifies the reference. This string is
binary-encoded and contains unprintable characters. This is why we
truncated it to ...
in the output shown above.
If you want to use ReflectionReference
to check
whether a property of an object holds a reference then you need to
cast that object to an array first:
$object = new stdClass;
$object->foo = 'bar';
$reference = &$object->foo;
$array = (array) $object;
var_dump(ReflectionReference::fromArrayElement($array, 'foo')->getId());
This will result in:
string(20) "..."
Again, we had to truncate the output, as you can tell by looking at the string length.