【问题标题】:Is there an array-to-callable function?是否有数组可调用函数?
【发布时间】:2016-04-09 20:33:37
【问题描述】:

设置

SomeClass 内有f2member 接受两个整数参数并产生其总和。测试通过,表明调用确实有效并检索到了预期的结果。调用$g,带有两个参数11 返回2

重要提示:这仅适用于 php 5.4.11 及更高版本 compatibility check

class SomeClass extends PHPUnit_Framework_TestCase
{   
    function f2member($a,$b)
    {
        return $a + $b;
    }

    /**
     * @test
     */
    public function test()
    {
        $g = array($this,'f2member');
        $this->assertEquals(2, $g(1,1)); // squiggle line under $g
    }
}

问题

但是,这会在每次方法调用时在 phpStorm 内部产生一个警告,并在 $g 下产生一条曲线:

函数名必须是可调用的——字符串、闭包或实现__invoke的类,当前为数组

警告的来源对我来说很清楚,现在我正在寻找避免这些警告的方法。 一个要求是,我不想改变调用函数的风格。我不想做的另一件事是停用此警告。 我宁愿在它周围包裹一些东西,为类型系统提供必要的信息。

尝试

我已经遇到了几种消除警告的解决方案。一种是定义一个用户定义的函数,它只记录所需的目标类型。

/**
 * @param array $arr
 *
 * @return callable
 */
function callable_for($arr)
{
    return $arr;
}

这将返回一个数组,但也明确地告诉类型系统 callable_for 函数的结果。有了这个类型注释,phpStorm 现在停止抱怨这个警告,尽管它仍然返回一个数组。

$g = callable_for(array($this,'f2member'));

问题

难道没有像我在 php 中的 callable_for 这样的开箱即用的东西来实现这一点吗?如果答案是否定的,那么 我正在寻找我们能找到的最简洁的解决方案。

我已经尝试查看 SO、php.net 和 google。也许,我只是搜索了错误的单词组合,这里只是两个示例:

  • 可调用 php 的数组
  • 创建可调用的方法句柄 php

大图

以防万一出现怀疑,这是X/Y problem:我有另一个函数将可调用对象作为参数。使用闭包,定义一些东西是很自然的,以后可以调用它。但是,如何在不将其包装在另一个委托闭包中的情况下为成员或静态方法定义可调用对象?数组表示法允许用于统一传递:闭包或静态/成员方法句柄到我以后的函数。我现在正试图找到一个简洁的解决方案,它接近于this

【问题讨论】:

    标签: php dynamic invocation method-invocation


    【解决方案1】:

    因此,另一个改进可能是修改callable_for 以接受两个参数并包装两个职责;创建数组并记录目标返回类型。

    /**
     * @param mixed $context
     * @param string $method
     *
     * @return callable
     */
    function callable_for($context, $method)
    {
        return array($context, $method);
    }
    

    使用此实现将$g 的声明的简洁性提高到可接受的水平。

    $g = callable_for($this,'f2member');
    

    这个函数仍然返回一个数组,但是类型系统可以使用给定的信息来正确处理这个数组以进行动态方法调用。

    【讨论】:

    • 这会返回一个数组,而不是可调用的。
    • @Pamblam 我更新了问题以反映我知道这会返回一个数组,但也增加了这种看起来尴尬的设置的动机。
    • 我删除了我的答案,显然我不明白你的问题,但在回复你的其他评论时,我很想看看你如何调用数组,如果你愿意发布的话一个例子..
    • @Pamblam 没有人是完美的,只需在问题中给定的 phpunit 测试上运行 phpunit。这个赋值$g = array($this, 'f2member'); 中的数组将被转换成可以传递参数列表的东西,当在它上面调用$g(1,1) 时,它应该评估如预期的。然后这将返回2 并让测试用例中的断言通过。或者直接点击this link。但是,从右侧的链接答案中,我得到了可能不鼓励这种风格的信息。
    • 哇,这真是太酷了,谢谢分享。我很抱歉怀疑你:p 然而,如果你看看你的 3v4l,它会显示 php
    【解决方案2】:

    这个问题是四年前提出的,但经过一些研究后我发现了 Closure::fromCallable 方法:https://www.php.net/manual/de/closure.fromcallable.php

    【讨论】:

      猜你喜欢
      • 2017-12-20
      • 2022-01-06
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      相关资源
      最近更新 更多