Переопределить PHP-докблок / аннотацию метода без перегрузки (автозаполнение PhpStorm)

Это вопрос о поведении автозаполнения в PhpStorm (и, возможно, других IDE) в сочетании с докблоками PHP.

У меня есть группы классов в моем приложении. Во-первых, существуют отдельные классы для различных продуктов (CarProduct, FoodProduct и т. Д.), Все они наследуются от BaseProduct, и аналог для отдельных контрактов (CarContract, FoodContract и т. Д.), Все они наследуются от BaseContract.

<?php

class BaseContract
{
    /** @var BaseProduct */
    private $product;

    /**
     * @return BaseProduct
     */
    public function getProduct()
    {
        return $this->product;
    }
}

Теперь у меня есть экземпляр CarContract, и я хочу получить определенную информацию о CarProduct:

<?php

/* PhpStorm thinks, this is BaseProduct */
$product = $carContract->getProduct();

/* hence, getSpeed() is not available for PhpStorm */
$product->getSpeed();

Автозаполнение не работает, как мне нравится. Есть два обходных пути для этого, но оба не хороши:

  1. Перегрузка getProduct() в подклассе, только с обновленным @return docblocks
  2. добавлять /** @var CarProduct $product */ везде, где я получаю доступ к продукту CarContract

Есть ли "обычный" способ решить что-то подобное или мои обходные пути - единственные решения?

1 ответ

PhpStorm на самом деле не позволяет / не поддерживает выполнение чего-то подобного: иметь такой же именованный класс, определенный в другом месте, и просто использовать его как ссылку для переопределения определений реального класса. Вы можете сделать это... но IDE выдаст предупреждение с "несколькими определениями одного и того же класса", и это может привести к странному поведению / неожиданным предупреждениям...

Вот билет, который запрашивает такую ​​функцию: https://youtrack.jetbrains.com/issue/WI-851 - смотрите его (звезда / голосование / комментарий), чтобы получать уведомления о любом прогрессе.


Ваши варианты: вы можете предоставить правильный тип подсказки локально (для локальной переменной), используя @var - вы уже знаете это, и это первое, что вы подумали бы о:

<?php

/** @var \CarProduct $product */
$product = $carContract->getProduct();

$product->getSpeed();

Другой возможный способ: вместо переопределения фактического метода.. вы можете попробовать сделать то же самое, но с @method PHPDoc - будет работать с вашим кодом:

<?php
/**
 * My Car Product class
 * 
 * @method \CarProduct getProduct() Bla-bla optional description
 */
class CarContract extends BaseContract ...
Другие вопросы по тегам