Php 确定调用\u user\u func\u数组的类

Php 确定调用\u user\u func\u数组的类,php,Php,是否可以找到调用call\u user\u func\u array方法的类的名称?下面是一个例子: // ClassA public static function __callStatic($method, $args) { return call_user_func_array([ClassB::some_method(static::$some_arg), $method], $args); } // ClassB public static function some_met

是否可以找到调用
call\u user\u func\u array
方法的类的名称?下面是一个例子:

// ClassA
public static function __callStatic($method, $args)
{
    return call_user_func_array([ClassB::some_method(static::$some_arg), $method], $args);
}

// ClassB
public static function some_method($some_arg) {
    // how do I find out that some_method was called by ClassA?
}
目标是让
some_方法
知道它是由
ClassA
调用的。还要注意的是
ClassB::some_方法(static::$some_arg)
静态调用该方法,然后
call_user_func_数组中的
$method
与之链接

另一方面,我尝试用
returndb::some_方法(static::$some_arg)->$方法(extract($args))替换
call_user_func_数组
,但它没有按预期工作。有什么原因吗

编辑 我对最初的问题有点复杂。现在想象一下,有一个类
ClassA\u Child

class ClassA_Child extends ClassA {}
ClassA\u Child
现在可以调用
ClassB
的方法--
some\u方法
。电话是

ClassA_Child::some_method;
这是有效的,因为
ClassA\u Child
ClassA
的子类。但是,如果我执行以下操作:

// ClassB
public static function some_method($some_arg) {
    $bt = debug_backtrace();
    $caller_class = (isset($bt[1]['class']) ? $bt[1]['class'] : null);
    echo $caller_class; // ClassA, and NOT ClassA_Child!
}

请注意,回溯表示基类
ClassA
调用了
some\u方法,而不是
ClassA\u子类
。有什么办法可以解决这个问题吗?

这个答案需要一些介绍。首先,讨论一下(那些在啤酒前社交的程序员)为什么你会想要这么复杂的间接引用,我使用的是相当复杂的ORM,它们不需要这么多的间接和抽象层次

另一个重要的注意事项是,可能有人会用一些非常哲理的论据评论说,出于这个和那个原因,您不应该采用
debug\u backtrace()
解决方案。这确实是一种糟糕的做法,但你猜怎么着,我也在用它。请注意,这是一个非常脆弱的编码,很多情况下都准备好了

以下是相关代码:

class A {
  static $some_arg = "ciao";

  public static function __callStatic($method, $args) {
    return call_user_func_array(array(B::some_method(static::$some_arg), $method), $args);
  }
}

class B {
  public static function some_method($some_arg) {
    print "B::some_method (" . $some_arg . ")\n";

    // obtain the caller class
    $bt = debug_backtrace();
    $caller_class = (isset($bt[1]['class']) ? $bt[1]['class'] : null);
    print ".. i was called by " . $caller_class . "\n";

    return "C";
  }
}

class C {
  public static function other_method($arg1, $arg2) {
    print "C::other_method called\n";
  }
}

A::other_method(10, 20);
输出:

B::some_method (ciao)
.. i was called by A
C::other_method called
called B::factory()
called c::m() a=10 b=20
更新#2

如果在
ClassA
的子类上调用
\u callStatic()
,而不是直接在
ClassA
中调用(如
ClassA\u Child::doSomething()
),则可以替换以下代码行以获取此信息。请注意,如果脚本直接调用
\uu callStatic()
本身(无论如何,这永远不会发生),则此更改(在调用堆栈上再上一层)将失败

更新

我不得不为问题的“旁注”部分编辑我的答案。我错了,因为我认为某些_method()会返回一个静态类名(基本上是一个字符串),而它实际上会返回一个实例

在这种情况下,如果愿意,您完全可以放弃调用_user_func_array(),但我更喜欢使用这种方法。您所做的唯一错误是提取($args)部分,该函数做的是而不是按照您的想法做,它实际上做了一些完全不同的事情,请查看手册页

这里需要的是spread运算符,如本例所示:

class B {
  static function factory() {
    print "called B::factory()\n";
    return new C();
  }
}

class C {
  function m($a, $b) {
    print "called c::m() a=$a b=$b\n";
  }
}

$func_name = "m";
$func_args = array(10, 20);
B::factory()->$func_name(...$func_args);
输出:

B::some_method (ciao)
.. i was called by A
C::other_method called
called B::factory()
called c::m() a=10 b=20

我感谢你详尽的回答!除了
调试_backtrace
,还有更安全的替代方法吗?至于旁注,
ClassB
中的
somemethod
返回一个
ClassB
的对象,然后在
call\u user\u func\u array
中调用的$method被链接到该对象上。不,我认为没有其他方法。正如我提到的,我也使用同样的技巧,尽管这不是很好的练习。当然,除了将
\uuuuu类作为参数传递给被调用函数本身之外..谢谢。我现在的问题是
ClassA
的子类(例如
ClassAChild
)实际上在
ClassB
中调用
某些方法,而不是
ClassA
本身。我在调试回溯中得到
ClassA
。有没有可能得到
ClassAChild
?我没有收到你的最后一条评论,你能展示一些与我类似的工作概念代码吗?我能执行的东西。调优$bt[1]部分可能就足够了,如果使用$bt[2],则在堆栈调用中上升两次。尝试在相关代码中使用var_dump(debug_backtrace()),您可能会明白我的意思。您可以看看我的编辑吗?我试图更详细地解释我当前的问题。我看到了您的编辑,正如我提到的,您是否只是尝试用$bt[2]替换$bt[1]?通过对堆栈进行升级,您可以看到静态调用是否发生在ClassA或ClassA_Child上。我认为某些方法应该接收一组参数,以允许它返回正确且一致的结果。如果需要从同一类中的多个位置调用函数,并且需要略有不同的结果,该怎么办。随着项目和团队的发展,这种类型的编码也很难记录和维护。