PHP 可调用对象作为对象成员
我有一个类 Logger
,其中有一个方法 Log
。
由于 Log
是 Logger
实例最常见的用途,因此我已连接 __invoke
来调用 Log
另一个类, “Site”包含一个成员“Log”,它是 Logger 的一个实例。
为什么这会起作用:
$Log = $this->Log;
$Log("Message");
但不是这样:
$this->Log("Message");
前者失败并显示“PHP 致命错误:调用未定义的方法 Site::Log()”
这是可调用对象实现的限制,还是我误解了什么?
I have a class Logger
which, among other things has a method Log
.
As Log
is the most common use of the Logger
instance, I have wired __invoke
to call Log
Another class, "Site" contains a member "Log", an instance of Logger.
Why would this work:
$Log = $this->Log;
$Log("Message");
But not this:
$this->Log("Message");
The former fails with "PHP Fatal error: Call to undefined method Site::Log()"
Is this a limitation of the callable object implementation, or am I misunderstanding something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不幸的是,这(仍然)是 PHP 的一个限制,但是当您仔细考虑时,这是有道理的,因为类可以包含共享名称的属性和方法。例如:
如果 PHP 允许使用您想要的语法,则会调用哪个函数?不幸的是,这只剩下
call_user_func[_array]()
(或者将$this->log
复制到另一个变量并调用它)。然而,如果以下语法可以接受那就太好了:
但遗憾的是,事实并非如此。
Unfortunately, this is (still) a limitation of PHP, but it makes sense when you think about it, as a class can contain properties and methods that share names. For example:
If PHP were to allow the syntax you desire, which function would be invoked? Unfortunately, that only leaves us with
call_user_func[_array]()
(or copying$this->log
to another variable and invoking that).However, it would be nice if the following syntax was acceptable:
But alas, it is not.
同样的原因,你不能这样做:
$value = $this->getArray()["key"];
甚至这个
$value = getArray()["key"] ;
因为 PHP 语法不能很好地进行速记。
Same reasons you can't do this:
$value = $this->getArray()["key"];
or even this
$value = getArray()["key"];
Because PHP syntax doesn't do short hand very well.
这可能有效:但也许使用完整调用更容易、更好?似乎没有一种方法可以在一条线上获得您想要的工作。
您问题中的错误表明它正在寻找在不存在的类上定义的函数。可调用对象不是函数,在这种情况下似乎不能将其视为函数。
This may work:But perhaps it's just easier and better to use the full call? There doesn't seem to be a way to get what you want to work on the one line.
The error in your question indicates it is looking for a function defined on the class which doesn't exist. An invokable object isn't a function, and it seems it can't be treated as one in this case.
从 php7.4 开始,以下代码对我有用
as of php7.4 the following code works for me
感谢您的问题和所有的答案!我将分享我的经验,以防它对这个主题上的人有用。
我喜欢以这样的方式定义调试函数,当调试标志打开时,程序会向我描述它正在做什么,并且在编写代码时添加大量日志记录,因为这是我知道的时间最好有哪些情况。然后,当调试标志关闭时,除了布尔检查之外几乎没有任何开销成本,因为仅在调试打开时才调用该函数(并评估参数)。
我以不同的方式在其他语言中使用它,在 PHP 中,我一开始是这样写的:
但随后它将在全局范围内:
而且我不想添加全局变量,因为全局变量不能放在一个命名空间。因此,在检查了命名空间中的内容之后,我在一个类中定义了它:
但它给了我该线程所说的相同的“未初始化”警告,并且不起作用!
感谢这个帖子和 Norbert Wagner 的推荐,我尝试使用括号,它成功了!我不需要将其添加到布尔检查中,只需在调用中添加它,现在代码如下所示并且可以工作:
Thank you for your question and for all the answers! I'll share my experience in case it comes useful for someone on this subject.
I love defining a debug function in such a way that the program, when debug flag is on, would describe to me what it's doing, and I add a lot of the logging when I write the code, as this is the time when I know best which cases can be there. Then when debug flag is off, there is almost no overhead cost except for boolean checks, since the function is called (and the parameters are evaluated) only in case debug is on.
I used it in other languages in a different way, and in PHP at first I wrote it like this:
but then it would be in the global scope:
and I didn't want to add global variables, which couldn't be put under a namespace. So after checking what can be in a namespace, I defined it inside a class:
but it gave me the same "uninitialized" warning this thread speaks about, and didn't work!
Thanks to this thread and Norbert Wagner's recommendation, I tried with parentheses and it worked! I didn't need to add it on the boolean check, only on the call, and now the code looks like this and works: