Case
我正在玩一个 laravel 项目,看看我是否可以使用闭包来实现我的排序接口,我注意到当我dd()
我的闭包时,它还显示了在其中创建闭包作为属性的类。
最小化代码
// 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);
}
someOtherFunction()
内部dd()
的结果:
^ Closure($p, $n) {#1308 ▼
class: "AppOrder"
use: {▼
$sortColumn: "created_at"
}
}
问题
从dd()
的结果来看,它表明闭包具有一个属性,该属性表明它是在类AppOrder
中定义的。有没有办法访问此值?
我已经尝试过get_class($fn)
但正如预期的那样,它给出了"Closure"
,如果我这样做$fn->class
它会给出一个错误,说Closure object cannot have properties
。
你可以在闭包上使用反射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
根据您需要查找的类返回一个ReflectionClass
实例,getName
完成作业。
当然,您可以通过 defaultSortFunction 中的参数将类名注入到闭包中,但这显然不是那么好。
您应该能够使用以下方法从调用堆栈中自行提取调用类: https://www.php.net/manual/en/function.debug-backtrace.php
如果使用 limit 参数,您应该能够将其限制为仅返回调用类,而不返回。
我不确定,但我怀疑它的性能不是特别好。