-
Notifications
You must be signed in to change notification settings - Fork 103
False Possitive in Abstract Respoitory classes mapped to Abstract Entity classes: "<entity> has no field or association named <field>" #525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This bug report is missing a link to reproduction at phpstan.org/try. It will most likely be closed after manual review. |
You should at least post some code that leads to this behaviour. |
I will post later this weekend when I get a chance. |
I've updated the These issues only surfaced when updating to latest Chunk One------ -------------------------------------------------------------------------------------------------------------
Line src/App/Repository/AbstractAppRepository.php
------ -------------------------------------------------------------------------------------------------------------
19 QueryBuilder: [Semantical Error] line 0, col 86 near 'active = 1': Error: Class
App\Entity\AbstractAppEntity has no field or association named active
40 QueryBuilder: [Semantical Error] line 0, col 86 near 'altId': Error: Class
App\Entity\AbstractAppEntity has no field or association named altId
49 QueryBuilder: [Semantical Error] line 0, col 86 near 'altId': Error: Class
App\Entity\AbstractAppEntity has no field or association named altId
82 QueryBuilder: [Semantical Error] line 0, col 86 near 'number = :number': Error: Class
App\Entity\AbstractAppEntity has no field or association named number
93 QueryBuilder: [Semantical Error] line 0, col 86 near 'active = 1 ORDER': Error: Class
App\Entity\AbstractAppEntity has no field or association named active
------ ------------------------------------------------------------------------------------------------------------- use App\Entity\AbstractAppEntity;
use Doctrine\ORM\EntityRepository;
/**
* @template TypeEntity of AbstractAppEntity
* @extends EntityRepository<TypeEntity>
*/
abstract class AbstractAppRepository extends EntityRepository
{
/** @return class-string<TypeEntity> */
abstract protected function getEntityClass(): string;
/** @return TypeEntity[] */
public function findAllActive(): array
{
return $this->getEntityManager()->createQueryBuilder()
->select('entity')
->from($this->getEntityClass(), 'entity')
->where('entity.active = 1') // PHPSTAN ERROR: "AbstractAppEntity has no field or association named active"
->getQuery()
->getResult();
}
/** @return TypeEntity|null */
public function findByAltId(string $altId, bool $active = null): ?AbstractAppEntity
{
$qb = $this->getEntityManager()->createQueryBuilder()
->select('entity')
->from($this->getEntityClass(), 'entity')
->where('entity.altId = :altId') // PHPSTAN ERROR: "AbstractAppEntity has no field or association named altId"
->setParameter('altId', $altId);
if (null !== $active) {
$qb->andWhere('entity.active = :active')
->setParameter('active', $active);
}
return $qb->getQuery()->getOneOrNullResult();
}
/**
* @param string[] $ids
* @return TypeEntity[]
*/
public function findAltIds(array $altIds): array
{
return $this->getEntityManager()->createQueryBuilder()
->select('entity')
->from($this->getEntityClass(), 'entity')
->where('entity.altId NOT IN (:altIds)') // PHPSTAN ERROR: "AbstractAppEntity has no field or association named altId"
->andWhere('entity.active = 1')
->setParameter('altIds', $altIds)
->getQuery()
->getResult();
}
/**
* @param array{
* number : int,
* prefix : string|null,
* suffix : string|null,
* } $options
*/
public function findLatest(array $options): ?AbstractAppEntity
{
$qb = $this->getEntityManager()->createQueryBuilder()
->select('entity')
->from($this->getEntityClass(), 'entity')
->where('entity.number = :number') // PHPSTAN ERROR: "AbstractAppEntity has no field or association named number"
->setParameter('number', $options['number']);
foreach (['prefix', 'suffix'] as $option) {
if (! empty($options[$option])) {
$qb->andWhere("entity.$option = :$option")
->setParameter($option, $options[$option]);
}
}
$result = $qb->orderBy('entity.id', 'ASC')
->setMaxResults(1)
->getQuery()
->getResult();
return $result ? $result[0] : null;
}
/** @return ?TypeEntity */
public function findLatestActive(): ?AbstractAppEntity
{
$results = $this->getEntityManager()->createQueryBuilder()
->select('entity')
->from($this->getEntityClass(), 'entity')
->andWhere('entity.active = 1') // PHPSTAN ERROR: "AbstractAppEntity has no field or association named active"
->orderBy('entity.id', 'DESC')
->setMaxResults(1)
->getQuery()
->getResult();
return $results ? $results[0] : null;
}
...
} use App\Common\Entity\AbstractCommonEntity;
use App\Common\Entity\CommonEntityInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* @ORM\MappedSuperclass(repositoryClass="App\Repository\AbstractAppRepository")
* @ORM\HasLifecycleCallbacks()
*/
abstract class AbstractAppEntity extends AbstractCommonEntity implements CommonEntityInterface
{
/**
* @Assert\NotBlank()
* @Assert\NotNull()
* @ORM\Column(name="active", type="boolean", nullable=false)
*/
protected bool $active; // PHPSTAN is wrong, the field exists.
/**
* @Assert\NotBlank()
* @Assert\NotNull()
* @ORM\Column(name="alt_id", type="string", nullable=false)
*/
protected string $altId; // PHPSTAN is wrong, the field exists.
/**
* @Assert\Range(min=1, max=10000)
* @ORM\Column(name="number", type="smallint", nullable=false)
*/
protected int $number; // PHPSTAN is wrong, the field exists.
/**
* @Assert\NotIdenticalTo("")
* @ORM\Column(name="prefix", type="string", nullable=true)
*/
protected ?string $prefix;
/**
* @Assert\NotIdenticalTo("")
* @ORM\Column(name="suffix", type="string", nullable=true)
*/
protected ?string $suffix;
public function getActive(): bool
{
return $this->active;
}
public function getAltId(): string
{
return $this->altId;
}
public function getNumber(): int
{
return $this->number;
}
public function getPrefix(): ?string
{
return $this->prefix;
}
public function getSuffix(): ?string
{
return $this->suffix;
}
public function setActive(bool $active): static
{
$this->active = $active;
return $this;
} Chunk Two ------ --------------------------------------------------------------------------------------------------------------------
Line tests/Default/Common/Controller/AbstractCommonControllerTestCase.php
------ --------------------------------------------------------------------------------------------------------------------
484 QueryBuilder: [Semantical Error] line 0, col 20 near 'id) FROM App\Common\Entity\AbstractCommonEntity': Error: Class
App\Common\Entity\AbstractCommonEntity has no field or association named id
------ -------------------------------------------------------------------------------------------------------------------- use App\Common\Entity\AbstractCommonEntity;
use App\Tests\Default\Common\AbstractWebTestCase;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
/** @template TypeEntity of AbstractCommonEntity */
abstract class AbstractCommonControllerTestCase extends AbstractWebTestCase
{
...
/** @param class-string<AbstractCommonEntity> $entityClass */
protected function getEntityCount(string $entityClass): int
{
// PHPSTAN ERROR: "AbstractCommonEntity has no field or association named id"
return (int) $this->em->createQueryBuilder()->select('count(entity.id)')->from($entityClass, 'entity')->getQuery()->getSingleScalarResult();
}
...
} use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
abstract class AbstractCommonEntity
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(name="id", type="integer", nullable=false)
*/
protected int $id; // PHPSTAN is wrong, the field exists.
final public function getId(): int
{
return $this->id;
}
/** Use this to check if an instance is new, in which case it won't have a database id */
final public function isIdSet(): bool
{
return isset($this->id);
}
final public function unsetId(): static
{
unset($this->id);
return $this;
}
} |
for some reason, upgrading |
I had to roll back that |
Hey, I'm sorry, but I don't see anything actionable I could use to fix these errors. If you find the time, please submit a failing test here. |
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. |
Bug report
Here is an example of what I am seeing. It is incorrect on all counts.
I don't know how to replicate this type of thing on phpstan.org given the Doctrine dependency. Let me know if you might have a suggestion.
Code snippet that reproduces the problem
No response
Expected output
no erros
Did PHPStan help you today? Did it make you happy in any way?
always :)
The text was updated successfully, but these errors were encountered: