class Foo
{
public function __construct()
{
$bar = new Bar();
$bar->test();
}
}
class Bar
{
public function test()
{
$trace = debug_backtrace();
if (isset($trace[1])) {
// $trace[0] is ourself
// $trace[1] is our caller
// and so on...
var_dump($trace[1]);
echo "called by {$trace[1]['class']} :: {$trace[1]['function']}";
}
}
}
$foo = new Foo();
interface someInterface // many classes may implement this interface
{
public function giveMeBar();
}
class Foo implements someInterface
{
public function __construct()
{
$bar = new Bar();
$bar->test($this);
}
public function giveMeBar() {
return 'Bar';
}
}
class Bar
{
public function test(someInterface $a)
{
echo $a->giveMeBar();
}
}
$foo = new Foo(); // prints "Bar"
8条答案
按热度按时间q9yhzks01#
你可以使用
debug_backtrace
,就像这样:var_dump
将输出:和
echo
:但是,尽管它看起来不错,但我不确定它是否应该在您的应用程序中作为“正常的东西”使用......实际上,这似乎很奇怪:在我看来,有了好的设计,方法就不需要知道是什么调用了它。
nc1teljy2#
这是一个线性解
从PHP7开始,根据文档这是不起作用的:http://php.net/manual/en/function.list.php因为我们不能有空属性,这里是一个小的更新:
yvt65v4c3#
您还可以让调用对象将自身作为参数传递
例如:
我从《设计模式:Erich Gamma等人在第278页关于“Mediator”结构模式的讨论中介绍了“可重用面向对象软件的元素”。
这种模式的目的是减少一组对象/类之间的多对多连接。您创建一个中介类,所有这些类都将其视为一个中心。这样,类就不需要知道彼此。中介处理交互。为了让中介了解它跟踪的类中的更改,它们可以将自己作为参数传递。或者可以使用“观察者”模式来实现中介器。
2018编辑:
我有时会使用上面代码的接口,如下所示:
8e2ybdfx4#
您可能可以使用debug backtrace来实现这一点,尽管这看起来有点笨拙。
另一种选择是,当您从另一个类中示例化该类时,向该类传递一个参数,并告诉它从何处调用该类。
pbwdgjma5#
至少,您可以使用debug_backtrace并对其进行分析以找到调用方法。
我想你应该也能用reflection API来做这件事,但是我已经很久没有用PHP了,我不记得具体是怎么做的了。
hiz5n14c6#
@帕斯卡·马丁:是的,在一般的应用程序中可能不需要它。但有时候它可能会很有用。考虑一下我自己的应用程序中的一个例子:
有一个Controller子类,它可以使用Template对象来准备它的输出。每个模板都有一个名称来引用它。当一个Controller需要一个模板时,它通过将该名称作为参数来请求TemplateManager。但是对于不同的Controller,可能有许多具有该名称的模板文件。Controller被用作插件,并且可能由不同的用户编写。因此它们使用的名称不能被控制为彼此不冲突。模板的名称空间是必需的。因此TemplateManager是Template对象的工厂,它需要模板名称和名称空间名称来定位正确的模板源文件。这个名称空间与特定的Controller的类名相关。
但是,在大多数情况下,每个Controller都将使用来自自己的命名空间的模板,只有在极少数情况下使用来自其他命名空间的模板。因此,每次调用TemplateManager::getTemplate()时指定命名空间会很麻烦。如果命名空间是可选的,并且默认为...**调用TemplateManager::getTemplate()的Controller!**这里是了解调用者的好地方。
当然,调用者Controller可以将其自身或其名称作为参数传递,但这与传递名称空间名称实际上没有太大区别,无论哪种方式都不是可选的。
但是如果你知道调用者,你可以使用这个信息在getTemplate()中自动默认命名空间,甚至不用麻烦调用者。它不需要知道getTemplate()是如何在它内部处理它的,以及它是如何知道正确的默认命名空间的。他只需要知道它是这样做的,并且如果真的需要,它可以选择性地传递任何其他命名空间。
jtjikinw7#
此函数在不使用debug_backtrace的情况下执行此工作:
mpgws1up8#
在名称空间B中的方法中使用,这将为您提供从名称空间A调用名称空间B中的方法的类。