On Thu, Jan 17, 2019 at 6:48 AM Stanislav Malyshev <smalys...@gmail.com> wrote:
> Hi! > > > I'd like to propose the addition of a ReflectionReference class, as > > described in the following RFC: > > https://wiki.php.net/rfc/reference_reflection > > Do I understand correctly that the main use case here is to know if two > variables (treating this term expansively) point, by reference, to the > same zval/location? If so, I'd probably prefer a function that gives > answer to exactly this question. > Nearly. The main use case is to compare an *arbitrary* number of references efficiently, rather than only two. As an example, consider something like this: $refs = []; foreach ($array as $key => $value) { $ref = ReflectionReference::fromArrayElement($array, $key); if (null !== $ref) { $refs[$ref->getId()][] = $key; } } This will partition the keys into groups that all point to the same reference. For $array = ['foo' => &$ref1, 'bar' => &$ref1, 'baz' => &$ref2, 'abc' => &$ref2] this will result in $refs = [$ref1Id => ['foo', 'bar'], $ref2Id => ['baz', 'abc']]. This is not exactly what we want to do, but it illustrates the general type of code that this API allows you to write. Currently proposed API sounds a bit weird to me - why it's only > constructed from array element? It looks like a strange limitation. > This is explained in the RFC: > Construction of ReflectionReference instances faces the following problem: A PHP function can either accept an argument by value or by reference. This needs to be declared in the function signature, making it impossible to distinguish whether the passed value was a reference originally or not. To determine whether or not something is a reference, access to the parent structure is necessary (which might be an array, object property table or symbol table). There is simply no other way to do this PHP short of introducing a new language construct specifically for this purpose, which I think is overkill. It's the same issue as debug_zval_dump() has (which strips references) and why XDebug has a xdebug_debug_zval() function which works on a pseudo-variable-name syntax instead. If you want to inspect whether something is a reference, you need access to the parent structure. The most general parent structure in PHP is an array, because this covers all of arrays (trivially), objects (via array cast) and even variables (via get_defined_vars() or $GLOBALS, depending on the kind of variable you're interested in.) Additionally, I'm not sure I understand whether there's a case for > "knowing whether array element is a reference to something" without it > being the use case above (i.e. comparing two things). I have no idea > what VarCloner does so it would be useful to have some clarity there. > > > The TL;DR is that some libraries need a way to detect references and > > determine whether two references are the same. They previously used an > ugly > > Is this the same case or two different cases? Also, why do they need to > do it - what they are doing with this information afterwards? > Nicolas can explain that better than me, but from what I understand VarCloner converts a PHP value (of arbitrary complexity) into an object representation that's more amenable to further processing. E.g. instead of having PHP references, there will be a common object that's used everywhere a certain PHP reference was used. So the first time we see a reference we want to create a stub object for it, and then if we see a reference again (stored in a different place) we want to replace it with the existing stub object. Nikita