Ошибка подсказки правильного типа, выдаваемая PHPStan в UserInterface в проекте Symfony

Недавно я начал использовать PHPStan (версия 0.12.19) в проекте Symfony 3.4, но я получаю сообщение об ошибке, которое, кажется, должно было быть легко разрешить, но я изо всех сил пытаюсь понять.

В настоящее время работает на уровне 7. Вот ошибка, которую я получаю при запуске:

vendor/bin/phpstan analyse

------ --------------------------------------------------------------------------------------------------------------
  Line   src/AppBundle/Controller/MapController.php
 ------ --------------------------------------------------------------------------------------------------------------
  94     Parameter #1 $user of static method AppBundle\Entity\MapMarker::createMapMarker() expects
         Symfony\Component\Security\Core\User\UserInterface, object given.

Это важные части MapController.php:

    $user = $this->getUser();

     $mapMarker = MapMarker::createMapMarker(
            $user,
            $latitude,
            $longitude
        );

Метод getUser - это метод Symfony, поэтому я не могу изменить эту часть: https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php:

/**
     * Get a user from the Security Token Storage.
     *
     * @return UserInterface|object|null
     *
     * @throws \LogicException If SecurityBundle is not available
     *
     * @see TokenInterface::getUser()
     *
     * @final since version 3.4
     */
    protected function getUser()
    {
        if (!$this->container->has('security.token_storage')) {
            throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
        }

        if (null === $token = $this->container->get('security.token_storage')->getToken()) {
            return null;
        }

        if (!\is_object($user = $token->getUser())) {
            // e.g. anonymous authentication
            return null;
        }

        return $user;
    }

И важные части MapMarker.php:

/**
     * @param UserInterface $user
     * @param double $latitude
     * @param double $longitude
     */
    private function __construct(UserInterface $user, $latitude, $longitude) {
        $this->createdBy = $user;
        $this->latitude = $latitude;
        $this->longitude = $longitude;
    }

    /**
     * @param UserInterface $user
     * @param double $latitude
     * @param double $longitude
     * @return MapMarker
     */
    public static function createMapMarker(UserInterface $user, $latitude, $longitude): MapMarker
    {
        return new self($user, $latitude, $longitude);
    }

Когда я выхожу $user instanceof UserInterface он возвращает истину - насколько я могу судить, он передает объект UserInterface, а не просто "объект", как указывает PHPStan.

И, наконец, вот мой конфигурационный файл phpstan.neon:

parameters:
    level: 7
    paths:
        - src
        - tests
    checkGenericClassInNonGenericObjectType: false
    checkMissingIterableValueType: false

Что мне не хватает?

2 ответа

Решение

Я думаю, вы, по крайней мере, поняли, в чем проблема: тип возвращаемого значения метода getUser является @return UserInterface|object|null пока createMapMarker ожидает экземпляр UserInterface.

Перед звонком createMapMarker вы должны проверить, что возвращаемое значение getUser на самом деле является экземпляром UserInterface и, наверное, простой /** @var UserInterface $user */ прямо на вершине $user объявление переменной исправит.

Более удобный способ справиться с этим (imo) - добавить

      /**
 * @method User|null getUser()
 */

в верхней части вашего класса контроллера (с правильным импортом)

      use App\Entity\User

/**
 * @method User|null getUser()
 */
class MapController extends...
Другие вопросы по тегам