phpstan/phpstan-symfony

Support Symfony Validator

wehostadm opened this issue · 6 comments

Hi,

I have plenty of errors due to Symfony Validor 👍

  Line   Validator\UserEmailValidator.php
 ------ --------------------------------------------------------------------------------------
  42     Access to an undefined property Symfony\Component\Validator\Constraint::$message.
         💡 Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property
 ------ --------------------------------------------------------------------------------------

Seems that phpStan does not understand this...

Is there something to configure ?

Thanks,

Please show a piece of code where you're experiencing this error.

@ondrejmirtes

Yes, the code of my custom validator

<?php

namespace App\Validator;

use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UserEmailValidator extends ConstraintValidator
{
    private $entityManager;
    private $userRepository;

    public function __construct(EntityManagerInterface $entityManager, UserRepository $userRepository)
    {
        $this->entityManager = $entityManager;
        $this->userRepository = $userRepository;
    }

    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value)
        {
            return;
        }

        // Get previous values
        $oldObject = $this->entityManager->getUnitOfWork()->getOriginalEntityData($this->context->getObject());

        $check = (is_array($oldObject) && !empty($oldObject) && $oldObject['email'] != $value) || empty($oldObject);
        if ($check)
        {
            $user = $this->userRepository->findOneBy(['email' => $value]);
            if (!$user)
            {
                return;
            }

            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ value }}', $value)
                ->addViolation()
            ;
        }
    }
}

And the Symfony constraint

<?php

namespace App\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class UserEmail extends Constraint
{
    /*
     * Any public properties become valid options for the annotation.
     * Then, use these in your validator class.
     */
    public $message = 'L\'email {{ value }} est déjà utilisé';
}

Then when I run the PhpStan with the Symfony extension enabled, I got these errors for each custom validator

 Line   Validator\UserEmailValidator.php
 ------ --------------------------------------------------------------------------------------
  42     Access to an undefined property Symfony\Component\Validator\Constraint::$message.
         💡 Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property
 ------ --------------------------------------------------------------------------------------

Thanks,

i have the same issue when i update phpstan/phpstan-symfony from 1.3.2 to 1.3.4

------ ----------------------------------------------------------------------------
  Line   src/Controller/Item/AvailabilityNotificationController.php
 ------ ----------------------------------------------------------------------------
  83     Call to an undefined method
         Symfony\Component\Validator\ConstraintViolationInterface::getConstraint().
 ------ ----------------------------------------------------------------------------

The corresponding code is:

78.    $error = $validator->validate($availabilityNotification);
79.
80.    $success = false;
81.
82.    if (count($error) > 0) {
83.      $first_constraint = $error[0]->getConstraint();
84.
85.      if ($first_constraint instanceof UniqueEntity) {
86.        $success = true;
87.      }
88.    }

$validator is autoinjected by ValidatorInterface $validator

My phpstan/phpstan version is 1.10.39

With phpstan/phpstan-symfony 1.3.2 i get no error, only when i update to 1.3.4

As explained in https://symfony.com/doc/current/validation/custom_constraint.html#creating-the-validator-itself, you should add a guard to ensure the constraint is the expected type:

if (!$constraint instanceof YourConstraint) {
    throw new UnexpectedTypeException($constraint, YourConstraint::class);
}

Now PHPStan should treat the constraint as your constraint class below the guard!

Situation could be improved with generics the same way security Voters work but that’s up to Symfony to decide.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.