如何在php中检查闭包?

7

我有一个函数,它接受一个闭包。我想知道这个闭包来自哪个方法。当我调用print_r时,它输出:

Closure Object
(
  [static] => Array
    (
      [listener] => Event_Subscriber_Calq@vendor_product_created
      [container] => Illuminate\Foundation\Application Object
...

如何访问那个监听器的值?我尝试使用 ->static、::$static、getStatic(),但无法想到任何方法来获取该值。
目前,我的计划是使用输出缓冲来捕获var_dump的输出。我不能使用print_r,因为闭包包含对自身引用的对象的引用,而print_r处理递归需要很长时间。我也不能使用var_export,因为它在输出中不包括我想要的值。所以,这是我的解决方案:
ob_start();
var_dump($closure);
$data = ob_get_clean();
$data = preg_replace('#^([^\n]*\n){4}#', '', $data);
$data = preg_replace('#\n.*#', '', $data);
$data = preg_replace('#.*string.[0-9]+. "(.*)".*#', '\1', $data);
list($class, $method) = explode('@', $data);

这很糟糕。有没有其他方法可以解决这个问题?也许可以使用反射?

它实际上来自于 Laravel,它扩展了核心 PHP 闭包类,但并没有添加任何新方法。 - Benubird
你尝试过将这个关联数组转换为数字数组吗?http://php.net/manual/zh/function.array-values.php - Gabriel Moretti
@Quasdunk,闭包通常是对匿名函数的引用,但它也可以是对命名函数的引用,这就是我认为我的情况...虽然仔细看看,我认为我更可能是试图从闭包的本地作用域中检索数据...不确定这甚至有任何意义。无论如何,我正在尝试获取 $obj->static->listener 的值。 - Benubird
@GabrielMoretti 是的,它会拒绝它,因为闭包是一个对象,而不是一个数组。 - Benubird
你从get_object_vars()得到了什么?@Benubird - Gabriel Moretti
显示剩余5条评论
2个回答

8

我知道这篇文章有点老了,但如果有人正在寻找相关信息, 你需要使用ReflectionFunction:

$r = new ReflectionFunction($closure);
var_dump($r, $r->getStaticVariables(), $r->getParameters());

问候, Alex


谢谢!这正是我所需要的 - 我需要获取给定事件的监听器类名。 - guice

0
在最近的一个项目中,我决定采用声明式方法,使用包装类。该类允许设置自由格式字符串来描述回调的来源,并且可以直接替换闭包,因为它实现了__invoke()方法。
例如:
use ClosureTools;

$closure = new NamedClosure(
    function() {
        // do something
    }, 
    'Descriptive text of the closure'
);

// Call the closure
$closure();

访问有关闭包的信息:

if($closure instanceof NamedClosure) {
    $origin = $closure->getOrigin();
}

由于起点是自由格式的字符串,因此可以根据用例将其设置为有用的内容以识别闭包。

以下是类骨架:

<?php

declare(strict_types=1);

namespace ClosureTools;

use Closure;

class NamedClosure
{
    /**
     * @var Closure
     */
    private $closure;

    /**
     * @var string
     */
    private $origin;

    /**
     * @param Closure $closure
     * @param string $origin
     */
    public function __construct(Closure $closure, string $origin)
    {
        $this->closure = $closure;
        $this->origin = $origin;
    }

    /**
     * @return string
     */
    public function getOrigin() : string
    {
        return $this->origin;
    }

    public function __invoke()
    {
        return call_user_func($this->closure, func_get_args());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接