How to create fixture where there is relation between two tables in Symfony?

3.9k Views Asked by At

I have two entities say 'User' and 'Address' in which I have 'OneToOne' relation between them.

User table has a column 'address_id' which is Foreign key, stores the id of Address table. I have tried to create fixture by using 2 different methods:

Method 1:

AddressFixture.php

namespace App\DataFixtures;

use App\Entity\Address;
use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class AddressFixture extends Fixture
{
    public function __construct(UserPasswordEncoderInterface $encoder)
    {
        $this->encoder = $encoder;
    }
    public function load(ObjectManager $manager)
    {
        $address = new Address();
        $address->setStreet('Sai Apartment');
        $address->setCity('Noida');
        $address->setState('Uttar Pradesh');
        $address->setCountry('India');
        $address->setPincode('201301');
        $manager->persist($address);
        $manager->flush();
        if (null != $address->getId()) {
            $user = new User();
            $user->setFName('Kumar');
            $user->setLName('Saurabh');
            $user->setUsername('supa-admin');
            $user->setPassword(
                $this->encoder->encodePassword($user, 'querty')
            );
            $user->setEmail('[email protected]');
            $user->setAddress($address);
            $user->setContact(78954);
            $user->setGender('male');
            $user->setAge(26);

            $user->persist($user);
            $manager->flush();
        }
    }
}

Method 2:

In this I have created two different Fixtures:

AddressFixture.php

namespace App\DataFixtures;

use App\Entity\Address;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class AddressFixture extends Fixture
{
    public function load(ObjectManager $manager)
    {
        $address = new Address();
        $address->setStreet('Sai Apartment');
        $address->setCity('Noida');
        $address->setState('Uttar Pradesh');
        $address->setCountry('India');
        $address->setPincode('201301');
        $manager->persist($address);
        $manager->flush();
    }
}

UsersFixture.php

namespace App\DataFixtures;

use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class AddressFixture extends Fixture
{
    public function __construct(UserPasswordEncoderInterface $encoder)
    {
        $this->encoder = $encoder;
    }
    public function load(ObjectManager $manager)
    {
            $user = new User();
            $user->setFName('Kumar');
            $user->setLName('Saurabh');
            $user->setUsername('supa-admin');
            $user->setPassword(
                $this->encoder->encodePassword($user, 'querty')
            );
            $user->setEmail('[email protected]');
            $user->setAddress($address);
            $user->setContact(78954);
            $user->setGender('male');
            $user->setAge(26);

            $user->persist($user);
            $manager->flush();
    }
}

Then I ran:

$ php bin/console doctrine:fixtures:load

Both ways did not gave me the required result. How to create Fixtures when Foreign key is used between both tables?

1

There are 1 best solutions below

1
On

You should implement DependentFixtureInterface in your UserFixture:

class UserFixture extends Fixture implements DependentFixtureInterface
{

   public function getDependencies()
    {
        return [
            AddressFixture::class,
        ];
    }

}

So when you try to get reference for your User, SymfonyFixturesLoader will load all dependencies. Then in your UserFixture just inject it to your address field:

public function load(ObjectManager $manager)
{
   $user = new User();
   // ...
   $user->setAddress($this->getReference(AddressFixture::FIRST_ADDRESS));
}

Do not forget to set reference on the AddressFixture side:

public function load(ObjectManager $manager)
{
   $address = new Address();
   // ...
   $this->setReference(self::FIRST_ADDRESS, $address);
}