检测PHP变量是否是引用/被引用
PHP 有没有办法确定给定变量是否是对另一个变量的引用和/或被另一个变量引用?我意识到,鉴于 在 php.net 上评论该设置 $a=& $b
表示“$a 和 $b 在这里完全相等。$a 不指向 $b,反之亦然。$a 和 $b 指向同一个地方。”
如果无法确定给定变量是否是引用/被引用,是否有通用方法来确定两个变量是否相互引用?同样,php.net 上的 注释 提供了一个函数这样的比较 - 尽管它涉及编辑一个变量并查看另一个变量是否受到类似的影响。如果可能的话,我宁愿避免这样做,因为我正在考虑的一些变量大量使用了魔术 getters/setters。
本例中请求的背景是编写一个调试函数来帮助详细查看结构。
Is there a way in PHP to determine whether a given variable is a reference to another variable and / or referenced by another variable? I appreciate that it might not be possible to separate detecting "reference to" and "reference from" given the comment on php.net that setting $a=& $b
means "$a and $b are completely equal here. $a is not pointing to $b or vice versa. $a and $b are pointing to the same place."
If it's not possible to determine whether a given variable is a reference / referenced, is there a generalised way of determining if two variables are references of each other? Again, a comment on php.net supplies a function for doing such a comparison - although it is one that involves editing one of the variables and seeing if the other variable is similarly effected. I'd rather avoid doing this if possible since some of the variables I'm considering make heavy use of magic getters / setters.
The background to the request in this instance is to write a debugging function to help view structures in detail.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用
debug_zval_dump
:这在 PHP 5.4 中不再起作用,因为它们被删除了调用时间通过引用支持,并且可能在较低版本上引发
E_STRICT
级别错误。如果你想知道上面函数中的
-4
从何而来:你告诉我......我通过尝试得到了它。在我看来,它应该只有 3 个(变量、函数中的变量、传递给 zend_debug_zval 的变量),但我不太擅长 PHP 内部,似乎它又创建了另一个途中某处参考;)You can use
debug_zval_dump
:This though will not work anymore as of PHP 5.4 as they removed call time pass by reference support and may throw an
E_STRICT
level error on lower versions.If you wonder, where the
-4
in the above function come from: You tell me... I got it by trying. In my eyes it should be only 3 (the variable, the variable in my function, the variable passed tozend_debug_zval
), but I'm not too good at PHP internals and it seems that it creates yet another reference somewhere on the way ;)完整的工作示例:
Full working example:
也许 xdebug_debug_zval() 对您有帮助。 http://www.xdebug.org/docs/all_functions
Maybe xdebug_debug_zval() helps you. http://www.xdebug.org/docs/all_functions
在 xdebug_debug_zval() 处获取峰值。现在,这是真正了解是否可以确定有关变量 zval 的所有信息的唯一方法。
因此,这里有几个辅助函数来确定一些有用的信息:
因此,使用一些示例变量:
我们可以测试变量是否是引用:
我们可以获取链接到 zval 的变量的数量(不一定是引用,可以用于写时复制):
我们可以测试是否可以写时复制(不执行内存复制的情况下复制):
我们可以测试是否可以在不复制 zval 的情况下进行引用:
现在,我们可以检查是否变量通过一些黑魔法引用自身:
这有点hacky,因为我们无法确定哪些其他符号引用了相同的zval(只有其他符号引用)。因此,这基本上检查
$a
是否是引用,以及$a
和$b
是否都具有相同的引用计数和引用标志集。然后,它更改一个以检查其他是否发生更改(表明它们是相同的引用)。Take a peak at xdebug_debug_zval(). Right now, that's the only way to really know if you can determine everything about the variable's zval.
So here are a couple of helper functions to determine some helpful information:
So with some sample variables:
We can test if a variable is a reference:
We can get the number of variables linked to the zval (not necessarily a reference, can be for copy-on-write):
We can test if we can copy-on-write (copy without performing a memory copy):
And we can test if we can make a reference without copying the zval:
And now, we can check if a variable references itself through some black magic:
It's a bit hacky since we can't determine what other symbols reference the same zval (only that other symbols reference). So this basically checks to see if
$a
is a reference, and if$a
and$b
both have the same refcount and reference flag set. Then, it changes one to check if the other changes (indicating they are the same reference).编辑:
看来我已经回答了“是否可以检查两个变量是否在内存中引用相同的值”的问题,而不是提出的实际问题。 :P
就“普通”变量而言,答案是“否”。
就物体而言——也许吧。
默认情况下,所有对象均由引用处理。此外,每个对象都有其序列号,您可以在
var_dump()
时看到该序列号。如果你能以某种方式得到这个#,你就可以有效地比较两个变量,看看它们是否指向同一个对象。问题是如何得到这个数字。
var_export()
不返回它。我在Reflection
类中也没有看到任何可以得到它的东西。我想到的一件事是使用输出缓冲+正则表达式
Edit:
It seems I've answered the question 'is it possible to check if two variables are referencing same value in memory' not the actual question asked. :P
As far as 'plain' variables go the answer is 'no'.
As far as objects go - maybe.
All objects are by default handled by references. Also each object has it's serial number which you can see when you
var_dump()
it.If you could get somehow to this #, you could effectively compare it for two variables, and see if they point to the same object. The question is how to get this number.
var_export()
does not return it. I don't see snything inReflection
classes that would get it either.One thing that comes to my mind is using output buffering + regex