简体   繁体   中英

PHP dynamic return type hinting

Suppose I have the following PHP function:

/**
 * @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);
}

Basically, the function always returns either an instance of the class specified with the $className parameter or null , if something went wrong. The only catch is, that I do not know the full list of classes this function can return. (at compile time)

Is it possible to get type hinting for the return type of this kind of function?

In Java, I would simply use generics to imply the return type:

static <T> T getOneObject(Class<? extends T> clazz, ParameterStorage parameters) {
    ...
}

I am aware of the manual type hinting, like

/** @var Foo $foo */
$foo = getOneObject('Foo', $params);

but I would like to have a solution that does not require this boilerplate line.

To elaborate: I am trying to write a wrapper around Doctrine, so that I can easily get the model entities that I want, while encapsulating all the specific usage of the ORM system. I am using PhpStorm.

** edited function to reflect my intended usage. I originally wanted to keep it clean of any specific use case to not bloat the question. Also note, that the actual wrapper is more complex, since I also incorporate model-specific implicit object relations and joins ect.

这现在可以通过 IntellJ (IDEA/phpStorm/webStorm) 插件 DynamicReturnTypePlugin 实现: https : //github.com/pbyrne84/DynamicReturnTypePlugin

I use phpdoc @mehtod for this purpose. For example, I create AbstractRepository class which is extend by other Repository classes. Suppose we have AbstractRepository::process(array $results) method whose return type changes according to the class that extends it. So in sub class:

/**
* @method Car[] process(array $results)
*/
class CarRepo extends AbstractRepository {
    //implementation of process() is in the parent class
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM