直接调用分配给对象属性的闭包
我希望能够直接调用分配给对象属性的闭包,而无需将闭包重新分配给变量然后调用它。这可能吗?
下面的代码不起作用并导致致命错误:调用未定义的方法 stdClass::callback()
。
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
I would like to be able to call a closure that I assign to an object's property directly without reassigning the closure to a variable and then calling it. Is this possible?
The code below doesn't work and causes Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
从 PHP 7 开始,可以调用闭包使用
call()
方法:自 PHP 7 可以对任意
(... )
表达式(如 Korikulum 所解释):其他常见的 PHP 5 方法是:
使用魔术方法
__invoke()
(如Brilliand所解释)使用
call_user_func()
函数在表达式中使用中间变量
每种方式都有自己的优点和缺点,但最根本和最明确的解决方案仍然是 戈登。
Since PHP 7 a closure can be called using the
call()
method:Since PHP 7 is possible to execute operations on arbitrary
(...)
expressions too (as explained by Korikulum):Other common PHP 5 approaches are:
using the magic method
__invoke()
(as explained by Brilliand)using the
call_user_func()
functionusing an intermediate variable in an expression
Each way has its own pros and cons, but the most radical and definitive solution still remains the one presented by Gordon.
似乎可以使用
call_user_func()
。不过,这并不优雅……@Gordon 所说的可能是唯一的出路。
It seems to be possible using
call_user_func()
.not elegant, though.... What @Gordon says is probably the only way to go.
好吧,如果你真的坚持的话。另一个解决方法是:
但这不是最好的语法。
但是,PHP 解析器始终将
T_OBJECT_OPERATOR
、IDENTIFIER
、(
视为方法调用。似乎没有解决方法可以使-> ;
绕过方法表并访问属性。Well, if you really insist. Another workaround would be:
But that's not the nicest syntax.
However, the PHP parser always treats
T_OBJECT_OPERATOR
,IDENTIFIER
,(
as method call. There seems to be no workaround for making->
bypass the method table and access the attributes instead.我知道这已经很旧了,但我认为如果您使用 PHP 5.4+,Traits 可以很好地处理这个问题。
首先,创建一个使属性可调用的特征:
然后,您可以在类中使用该特征:
现在,您可以通过匿名定义属性函数并直接调用它们:
I know this is old, but I think Traits nicely handle this problem if you are using PHP 5.4+
First, create a trait that makes properties callable:
Then, you can use that trait in your classes:
Now, you can define properties via anonymous functions and call them directly:
好吧,应该强调的是,将闭包存储在变量中,然后调用该变量实际上(奇怪地)更快,具体取决于调用量,它变得相当多,使用 xdebug (非常精确的测量),我们正在谈论1,5(这个因子,通过使用一个变量,而不是直接调用 __invoke.so ,而是将闭包存储在一个变量中并调用它。
well, it should be emphisized that storing the closure in a variable, and call the varible is actually (wierdly) faster, depending on the call amount, it becomes quite a lot, with xdebug (so very precise measuring), we are talking about 1,5 (the factor, by using a varible, instead of directly calling the __invoke. so instead , just store the closure in a varible and call it.
这是基于已接受答案但直接扩展 stdClass 的另一种选择:
用法示例:
不过,您可能最好使用
call_user_func
或__invoke
。Here's another alternative based on the accepted answer but extending stdClass directly:
Usage example:
You are probably better off using
call_user_func
or__invoke
though.更新:
PHP >= 7:
PHP >= 5.4:
Updated:
PHP >= 7 :
PHP >= 5.4 :
如果您使用 PHP 5.4 或更高版本,您可以将可调用对象绑定到对象的范围以调用自定义行为。因此,例如,如果您要进行以下设置..
并且您正在对这样的类进行操作..
您可以运行自己的逻辑,就像在对象范围内进行操作一样
If you're using PHP 5.4 or above you could bind a callable to the scope of your object to invoke custom behavior. So for example if you were to have the following set up..
And you were operating on a class like so..
You could run your own logic as if you were operating from within the scope of your object
我注意到这在 PHP5.5 中
有效 允许创建一个闭包的伪对象集合。
I note that this works in PHP5.5
Allows one to create a psuedo-object collection of closures.
从 PHP7 开始,您可以执行
或使用 Closure::call()这在
StdClass
上不起作用。在 PHP7 之前,您必须实现神奇的
__call
方法来拦截调用并调用回调(这对于StdClass
当然是不可能的,因为您无法添加__call
方法)请注意,您不能
在
__call
主体中执行此操作,因为这会在无限循环中触发__call
。As of PHP7, you can do
or use Closure::call(), though that doesn't work on a
StdClass
.Before PHP7, you'd have to implement the magic
__call
method to intercept the call and invoke the callback (which is not possible forStdClass
of course, because you cannot add the__call
method)Note that you cannot do
in the
__call
body, because this would trigger__call
in an infinite loop.您可以通过在闭包上调用 __invoke 来做到这一点,因为这是对象用来表现得像函数一样的神奇方法:
当然,如果回调是数组或字符串(这也可以是 PHP 中的有效回调),那么这将不起作用- 仅适用于闭包和其他具有 __invoke 行为的对象。
You can do this by calling __invoke on the closure, since that's the magic method that objects use to behave like functions:
Of course that won't work if the callback is an array or a string (which can also be valid callbacks in PHP) - just for closures and other objects with __invoke behavior.
从 PHP 7 开始,您可以执行以下操作:
As of PHP 7 you can do the following: