3

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('some_email@gmail.com');
            $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('some_email@gmail.com');
            $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?

Saurabh
  • 432
  • 1
  • 10
  • 23
  • The first one looks fine - you can drop out the `if (null != $address->getId())` part and do the flush just once after both entities are created and persisted. Or what exactly is not working for you in the first version? If you want to use separate fixtures you should take a look how the fixtures can be ordered and how previously created entities can be accessed from [doctrine sharing objects between fixtures](https://symfony.com/doc/2.0/bundles/DoctrineFixturesBundle/index.html#sharing-objects-between-fixtures) – ejuhjav Mar 25 '19 at 11:54
  • 1
    There is a little mistake `$user->persist($user);`. It should be `$manager->persist($user);` in method 1 – Constantin Mar 25 '19 at 12:20
  • @Constantin: thanks buddy for pointing out. It was a silly mistake from my side. – Saurabh Mar 25 '19 at 12:23
  • 1
    In method 2, in file UsersFixture.php, the class should be named `UsersFixture` instead of `AddressFixture `. Also I don't understand from where the variable `$address` comes from. You can use the `$manager` to find your `$address` entity. – Constantin Mar 25 '19 at 12:27

1 Answers1

6

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);
}
Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115
alvery
  • 1,863
  • 2
  • 15
  • 35
  • where did the FIRST_ADDRESS came from? I receive `Undefined class constant 'FIRST_ADDRESS'` – Shulz May 13 '23 at 13:57