PHP 闭包 - 获取 class 闭包作用域名称

PHP Closures - Getting class name of closure scope origin

案例

我正在玩一个 laravel 项目,看看我是否可以使用闭包来实现排序接口,我注意到当我 dd() 我的闭包时,它还显示了class 其中闭包创建为 属性.

最小化代码

// in my Order model class, i have a function that will return a closure
public static function defaultSortFunction(){
    $sortColumn = property_exists(self::class,'defaultSortingColumn') ? self::$defaultSortingColumn : 'created_at';

    return function($p,$n)use($sortColumn){
        return $p->$sortColumn <=> $n->$sortColumn;
    };
}
// in one of my controller I use for testing, I added these 2 methods for testing
public function index(){
    $sortFunction = Order::defaultSortFunction();
    $this->someOtherFunction($sortFunction);
    return 'done';
}

private function someOtherFunction($fn){
    dd($fn);

    // $scopeModel = get_class($fn); => Closure
    
    // example of how I can use this value later
    // $scopeModel::take(10)->get()->sort($fn);
}

dd()里面someOtherFunction()的结果:

^ Closure($p, $n) {#1308 ▼
  class: "App\Order"
  use: {▼
    $sortColumn: "created_at"
  }
}

问题

dd() 的结果可以看出,闭包有一个 属性,表明它是在 class App\Order 中定义的。 有什么方法可以访问这个值

我已经尝试了 get_class($fn),但正如预期的那样,它给出了 "Closure",如果我尝试了 $fn->class,它给出了一个错误提示 Closure object cannot have properties

您当然可以通过 defaultSortFunction 中的参数将 class 名称注入到闭包中,但这显然不太好。

您应该能够使用以下方法自行从调用堆栈中提取调用 class: https://www.php.net/manual/en/function.debug-backtrace.php

如果您使用 limit 参数,您应该能够将其限制为仅返回调用 class 而不再返回。

我不确定,但我怀疑它的性能不是特别好。

您可以在闭包中使用反射 API,这比 debug_backtrace

更简洁
// in one of my controller I use for testing, I added these 2 methods for testing
public function index(){
    $sortFunction = Order::defaultSortFunction();
    $this->someOtherFunction($sortFunction);
    return 'done';
}

private function someOtherFunction($fn){
    $reflectionClosure = new \ReflectionFunction($fn);
    dd($reflectionClosure->getClosureScopeClass()->getName());
}

getClosureScopeClass returns 一个 ReflectionClass 实例基于 class 你需要找到并且 getName 完成工作。