我有一个接受回调作为参数的方法。我想在 PHPDoc 中为 class 方法 提供一个签名,它概述了要传递给该方法的 callback 函数 的参数,以便我的 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);
}
}
方法
bar
有一个参数$baz
,是一个回调函数。任何作为参数传递给 bar()
的函数都必须接受 ArrayObject
作为其唯一参数。
理想情况下,应该可以为
Callable
包含多个参数,就像任何其他方法一样。
当我写下面的代码时:
$foo = new Foo();
$foo->bar(function(
...然后我应该收到一个参数列表,该列表正确提示此函数调用接受的参数的类型(
ArrayObject
)。
这种事情可能吗? PHPStorm 或其他 IDE 是否支持它?即使没有 IDE 支持,是否有推荐/标准的记录方法?
PHP 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,它甚至会在匿名类中自动生成
__invoke
-方法的签名和正文。
我通过使用
static function
在课堂上定义一个 callable
来克服这个问题。该函数有自己的文档块,我只是在需要使用 PHPDoc 的@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 中运行良好。快速文档 允许轻松地从方法文档导航到原型文档。
我让我的原型函数抛出一个异常,以明确它不应该被调用。我可以使用
protected
或 private
范围,但是 PHPDoc 不会总是选择文档块来生成文档。
不幸的是,PhpStorm 无法跟踪回调的使用情况。在使用需要回调的方法时,它也不提供参数信息,但至少正式记录了回调。
这种方法还有一个额外的好处,即在运行时从原型的反射验证回调定义。
目前在 PhpStorm 中是不可能的。我什至想不出其他通过其他方式做相对相同的解决方案。
可以使用
callable
和\Closure
类型的提示。
举个例子:
/**
* @param callable(int, string): int $callable
*
* @return int
*/
function some(callable $callable): int
{
return $callable(1, 'foo-bar');
}
/**
* @param Closure(\stdClass, array): void $closure
*
* @return mixed
*/
function some2(\Closure $closure): int
{
return $closure((object) [], []);
}
注意:只有当你提供 return typehint 时它才有效。
/**
* @param callable(): int $callable - Work
* @param callable: int $callable - Don't work (missed arguments)
* @param callable(int, int, string) - Don't work (missed return type hint)
* @param callable(int, int, SomeClass): void - Work
*/
PhpStorm 和静态分析器(例如phpstan)很好地正确阅读这些符号。