Как создать фикстуру, в которой есть связь между двумя таблицами в Symfony?

У меня есть два объекта: «Пользователь» и «Адрес», в которых у меня есть отношение «Один к одному» между ними.

Пользовательская таблица имеет столбец «address_id», который является Внешний ключ, хранит идентификатор Таблица адресов. Я попытался создать приспособление, используя 2 разных метода:

Способ 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();
        }
    }
}

Способ 2:

В этом я создал два разных прибора:

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();
    }
}

Затем я побежал:

$ php bin/console doctrine:fixtures:load

Оба способа не дали мне требуемого результата. Как создать Fixture, когда между обеими таблицами используется внешний ключ?

Первый выглядит нормально — вы можете удалить часть if (null != $address->getId()) и выполнить сброс только один раз после того, как обе сущности будут созданы и сохранены. Или что именно у вас не работает в первой версии? Если вы хотите использовать отдельные приборы, вы должны посмотреть, как можно упорядочить приборы и как получить доступ к ранее созданным объектам из доктрина совместного использования объектов между приборами.

ejuhjav 25.03.2019 12:54

Есть небольшая ошибка $user->persist($user);. Должно быть $manager->persist($user); в способе 1

Constantin 25.03.2019 13:20

@Constantin: спасибо, приятель, что указал. Это была глупая ошибка с моей стороны.

Saurabh 25.03.2019 13:23

В методе 2 в файле UsersFixture.php класс должен называться UsersFixture вместо AddressFixture . Также я не понимаю, откуда взялась переменная $address. Вы можете использовать $manager, чтобы найти свою $address сущность.

Constantin 25.03.2019 13:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
3
4
2 004
1

Ответы 1

Вы должны внедрить DependentFixtureInterface в свой UserFixture:

class UserFixture extends Fixture implements DependentFixtureInterface
{

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

}

Поэтому, когда вы пытаетесь получить ссылку для своего пользователя, SymfonyFixturesLoader загрузит все зависимости. Затем в своем UserFixture просто введите его в поле вашего адреса:

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

Не забудьте установить ссылку на стороне AddressFixture:

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

Другие вопросы по теме