phpstan / phpstan-doctrine

Doctrine extensions for PHPStan
MIT License
583 stars 96 forks source link

False positive for targetEntity interface #357

Open eerison opened 2 years ago

eerison commented 2 years ago

I'm not sure if it's a false positive or not, But I didn't know what to put in the title 😄

But I have this Interface

<?php

namespace App\Entity;

use Symfony\Component\Security\Core\User\UserInterface as BaseUserInterface;

interface UserInterface extends BaseUserInterface
{
    public function getId(): int;

    public function getEmail(): string;
}

and my User entity implements this interface

But for entities that join with user I'm getting this error

Property App\Entity\UserSocialNetworking::$user type mapping mismatch: property can contain App\Entity\UserInterface but database expects App\Entity\User.
    // UserSocialNetworking
    #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'userSocialNetworks')]
    #[ORM\JoinColumn(name: 'user_id', nullable: false)]
    protected UserInterface $user;

I tried to use this: https://symfony.com/doc/current/doctrine/resolve_target_entity.html But it doesn't work too!

any idea?

ondrejmirtes commented 1 year ago

Why not protected User $user;?

eerison commented 1 year ago

Why not protected User $user;?

Hmmmmm I don't remember to have test like it! I'll test and put here the results

shochdoerfer commented 1 year ago

I ran into a similar issue, I used MediaInterface everywhere but PHPStan still complained about the type mismatch.

This is my original definition:

#[ORM\ManyToOne(targetEntity: MediaInterface::class)]
#[ORM\JoinColumn(name: 'icon_id', referencedColumnName: 'id', onDelete: 'SET NULL')]
private ?MediaInterface $icon = null;

PHPStan was happy after I changed the code to make use of the Media entity:

#[ORM\ManyToOne(targetEntity: Media::class)]
#[ORM\JoinColumn(name: 'icon_id', referencedColumnName: 'id', onDelete: 'SET NULL')]
private ?Media $icon = null;

Interestingly, PHPStan only failed in CI. It worked fine locally. Could not figure why, the set-up locally and in CI looks identical to me.

usox commented 1 year ago

Hi

I'm facing the same issue. I'm using interfaces for my entites to decouple them from doctrine. Using User as typehint for the private property doesn't work as the setter method also requires the parameter to implement the UserInterface. I also configured a target entity resolver as the doctrine documentation suggests.

Why not protected User $user;?

    #[ORM\ManyToOne(targetEntity: UserInterface::class)]
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    private UserInterface $user;

    public function setUser(UserInterface $user): FavoriteInterface
    {
        $this->user = $user;
        return $this;
    }

    public function getUser(): UserInterface
    {
        return $this->user;
    }
Property Favorite::$user type mapping mismatch: property can contain UserInterface but database expects User
ambroisemaupate commented 1 year ago

Same issue with Collections

/**
 * @var Collection<int, AttributeInterface>
 */
#[ORM\OneToMany(mappedBy: "group", targetEntity: AttributeInterface::class)]
protected Collection $attributes;
Property RZ\Roadiz\CoreBundle\Entity\AttributeGroup::$attributes type mapping mismatch: property can contain Doctrine\Common\Collections\Collection<int, RZ\Roadiz\CoreBundle\Model\AttributeInterface> but database expects Doctrine\Common\Collections\Collection&iterable<RZ\Roadiz\CoreBundle\Entity\Attribute>.
mabumusa1 commented 1 year ago

Any solution for this issue?

fred-dedi commented 9 months ago

I ended up ignoring the error in the configuration :

    ignoreErrors:
        - '/Property .* type mapping mismatch: property can contain .*Interface.* but database expects .*/'

If the mapping is wrong, then bin/console doctrine:schema:validate should return an error.

trsteel88 commented 1 week ago

Same problem here. Was there a solution here other than ignoring it?