doctrine / data-fixtures

Doctrine2 ORM Data Fixtures Extensions
http://www.doctrine-project.org
MIT License
2.76k stars 224 forks source link

Psalm error for referenceRepository #424

Closed BigMichi1 closed 1 year ago

BigMichi1 commented 1 year ago

i followed the example given here to inject a service into the fixture.

now when i'm running psalm it prints out a warning that referenceRepository is not set in the constructor

ERROR: PropertyNotSetInConstructor - src/DataFixtures/UserFixtures.php:12:7 - Property App\DataFixtures\UserFixtures::$referenceRepository is not defined in constructor of App\DataFixtures\UserFixtures or in any methods called in the constructor (see https://psalm.dev/074)
class UserFixtures extends Fixture

my assumption is that it is because in AbstractFixture the type hint for referenceRepository only mentions ReferenceRepository but not null which could theoretically happen

greg0ire commented 1 year ago

You should show us the code of UserFixtures.php. There is no occurrence of referenceRepository in the page you linked.

BigMichi1 commented 1 year ago
<?php

declare(strict_types=1);

namespace App\DataFixtures;

use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class UserFixtures extends Fixture
{
    public const USER_ADMIN = 'user-admin';

    public const USER_MEMBER = 'user-member';

    public function __construct(
        private readonly UserPasswordHasherInterface $encoder
    ) {
    }

    public function load(ObjectManager $manager): void
    {
        $userAdmin = new User();
        $userAdmin->setEmail('admin@test.de');
        $userAdmin->setRoles(['ROLE_SUPER_ADMIN']);
        $userAdmin->setLocale('de');
        $userAdmin->setActive(true);
        $userAdmin->setFullName('Test Admin User');
        $userAdmin->setCreatedBy('fixture');
        $userAdmin->setUpdatedBy('fixture');
        $userAdmin->setPassword($this->encoder->hashPassword($userAdmin, '12345'));
        $manager->persist($userAdmin);

        $userMemeber = new User();
        $userMemeber->setEmail('member@test.de');
        $userMemeber->setRoles([]);
        $userMemeber->setLocale('de');
        $userMemeber->setActive(true);
        $userMemeber->setFullName('Test Member User');
        $userMemeber->setCreatedBy('fixture');
        $userMemeber->setUpdatedBy('fixture');
        $userMemeber->setPassword($this->encoder->hashPassword($userAdmin, '67890'));
        $manager->persist($userMemeber);

        $manager->flush();

        $this->addReference(self::USER_ADMIN, $userAdmin);
        $this->addReference(self::USER_MEMBER, $userMemeber);
    }
}
stof commented 1 year ago

The AbstractFixture of class doctrine/data-fixture indeed does not set the referenceRepository property in the constructor. However, it does set it through the setter before usage.

The issue here is that Psalm rejects valid PHP code in order to avoid having to model the uninitialized state of PHP properties (PHP requires a property to be initialized at the time you use it, not at the end of the constructor)

greg0ire commented 1 year ago

I think this should fix it: https://github.com/doctrine/data-fixtures/pull/425