如何使用 PHPDoc 对可调用对象的参数进行类型提示?

2022-08-30 13:44:06

我有一个接受回调作为参数的方法。我想在 PHPDoc 中为类方法提供一个签名,该签名概述了要传递给该方法的回调函数的参数,以便我的 IDE (PHPStorm) 可以为传递给我的方法的函数生成有效的类型提示,或者至少查看代码的人可以确定他们打算提供的回调的签名。

例如:

class Foo {
  public $items = [];
  /**
  * @param Callable(
  *   @param ArrayObject $items The list of items that bar() will return
  * ) $baz A callback to receive the items
  **/
  public function bar(Callable $baz) {
    $items = new ArrayObject($this->items);
    $baz($items);
  }
}

该方法有一个参数 ,它是一个回调函数。作为参数传递给 的任何函数都必须接受 a 作为其唯一参数。bar$bazbar()ArrayObject

理想情况下,应该可以为 包含 多个参数,就像任何其他方法一样。Callable

当我编写以下代码时:

$foo = new Foo();
$foo->bar(function(

...然后,我应该收到一个参数列表,该列表正确提示此函数调用的已接受参数的类型 ()。ArrayObject

这样的事情可能吗?PHPStorm或其他IDE是否支持它?即使没有IDE支持,是否有推荐/标准的方式来记录这一点?


答案 1

7+菲律宾比索:

将可调用的接口与匿名类结合使用将完成该操作。它不是很方便,并且导致类使用者的代码过于复杂,但目前它是静态代码分析方面的最佳解决方案。

/**
 * Interface MyCallableInterface
 */
interface MyCallableInterface{
    /**
     * @param Bar $bar
     *
     * @return Bar
     */
    public function __invoke(Bar $bar): Bar;
}

/**
 * Class Bar
 */
class Bar{
    /**
     * @var mixed
     */
    public $data = null;
}

/**
 * Class Foo
 */
class Foo{
    /**
     * @var Bar
     */
    private $bar = null;

    /**
     * @param MyCallableInterface $fn
     *
     * @return Foo
     */
    public function fooBar(MyCallableInterface $fn): Foo{
        $this->bar = $fn(new Bar);
        return $this;
    }
}

/**
 * Usage
 */
(new Foo)->fooBar(new class implements MyCallableInterface{
    public function __invoke(Bar $bar): Bar{
        $bar->data = [1, 2, 3];
        return $bar;
    }
});

如果你使用的是PhpStorm,它甚至会在匿名类中自动生成-Method的签名和正文。__invoke


答案 2

我克服了这个问题,方法是使用 .该函数有自己的文档块,我只是在需要使用PHPDoc的标签调用我可调用的方法中引用它。static functioncallable@see

class Foo
{
    /**
     * Description of the "bar" callable. Used by {@see baz()}.
     *
     * @param int $index A 1-based integer.
     * @param string $name A non-empty string.
     * @return bool
     * @see baz()
     * @throws \Exception This is a prototype; not meant to be called directly.
     */
    public static barCallable($index, $name)
    {
        throw new \Exception("barCallable prototype called");
    }

    /**
     * Description of the baz() method, using a {@see barCallable()}.
     *
     * @param callable $bar A non-null {@see barCallable()}.
     * @see barCallable()
     */
    public function baz(callable $bar)
    {
        // ...
        call_user_func($bar, 1, true);
        // ...
    }
}

这在PhpStorm 10中运行良好。快速文档允许轻松地从方法文档导航到原型文档。

我让我的原型函数抛出一个异常,以明确它不是要被调用的。我可以使用或范围,但PHPDoc并不总是选择文档块来生成文档。protectedprivate

不幸的是,PhpStorm无法跟踪回调的使用情况。当使用需要回调的方法时,它也不会提供参数信息,但回调至少是正式记录的。

此方法还具有从运行时的原型反射中验证回调定义的额外好处。


推荐