假设我有以下PHP函数:
/**
* @param string $className
* @param array $parameters
* @return mixed
*/
function getFirstObject($className, $parameters) {
// This uses a Doctrine DQl builder, but it could easily replaced
// by something else. The point is, that this function can return
// instances of many different classes, that do not necessarily
// have common signatures.
$builder = createQueryBuilder()
->select('obj')
->from($className, 'obj');
addParamClausesToBuilder($builder, $parameters, 'obj');
$objects = $builder
->getQuery()
->getResult();
return empty($objects) ? null : array_pop($objects);
}
基本上,如果出现问题,该函数总是返回用$className
参数指定的类的实例或null
。唯一的问题是,我不知道这个函数可以返回的类的完整列表。(编译时)
是否有可能获得这种函数返回类型的类型提示?
在Java中,我只使用泛型来暗示返回类型:
static <T> T getOneObject(Class<? extends T> clazz, ParameterStorage parameters) {
...
}
我知道手动类型的提示,如
/** @var Foo $foo */
$foo = getOneObject('Foo', $params);
但我想有一个解决方案,不需要这个样板行。
详细说明:我试图写一个包装器围绕Doctrine,这样我就可以很容易地得到我想要的模型实体,同时封装ORM系统的所有特定用法。我用的是PhpStorm
**编辑功能,以反映我的预期用途。我最初想让它不包含任何特定的用例,以免使问题膨胀。还要注意,实际的包装器更复杂,因为我还合并了特定于模型的隐式对象关系和连接等。
我使用phpdoc @method
用于此目的。例如,我创建了AbstractRepository
类,它由其他Repository类扩展。假设我们有一个AbstractRepository::process(array $results)
方法,它的返回类型根据扩展它的类而改变。在子类中:
/**
* @method Car[] process(array $results)
*/
class CarRepo extends AbstractRepository {
//implementation of process() is in the parent class
}
更新1:您也可以使用phpstan/phpstan
库。它用于静态代码分析,您可以使用它来定义泛型返回类型:
/**
* @template T
* @param class-string<T> $className
* @param int $id
* @return T|null
*/
function findEntity(string $className, int $id)
{
// ...
}
现在可以通过IntellJ (IDEA/phpStorm/webStorm)插件DynamicReturnTypePlugin实现:https://github.com/pbyrne84/DynamicReturnTypePlugin
如果你使用PHPStorm或VSCode(与扩展PHP Intelephense由Ben Mewburn)有一个名为元数据的实现,在那里你可以指定自己的类型提示基于你的代码做魔术里面。所以下面的代码应该可以工作(就像它在VSCode 1.71.2上所做的那样)
<?php
namespace PHPSTORM_META {
override(getFirstObject(0), map(['' => '$0']));
}