PHP动态返回类型提示


PHP dynamic return type hinting

假设我有以下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']));
}