Каскад Doctrine One To Many сохраняется, внешний ключ равен нулю

Я знаю, что в SA есть несколько тем об этом, но я не могу понять, почему мой код не работает ... Позвольте мне объяснить:

У меня есть компания, у которой может быть много связанных пользователей. Когда я создаю компанию, я хочу создать пользователя-администратора (первого пользователя), используя ту же форму.

Мои элементы:

class Company
{
    **
     * @ORM\Id
     * @ORM\GeneratedValue(strategy = "AUTO")
     * @ORM\Column(type = "integer")
    */
    private $id;
    ...

    /**
     * A company has many users.
     * @ORM\OneToMany(targetEntity = "User", mappedBy = "company", cascade = {"persist"})
     */
    private $users;
    ...

    public function __construct() {
        $this->users = new ArrayCollection();
    }

    public function addUser(User $user)
    {
        $user->setCompany($this);
        $this->users->add($user);
        return $this; // doesn't appear in the documentation but found in SA... doesn't change anything
    }

    public function removeUser(User $user)
    {
        // ...
    }

}


class User
{
    **
     * @ORM\Id
     * @ORM\GeneratedValue(strategy = "AUTO")
     * @ORM\Column(type = "integer")
    */
    private $id;
    ...

    /**
     * Many users belong to a company.
     * @ORM\ManyToOne(targetEntity = "Company", inversedBy = "users")
     * @ORM\JoinColumn(name = "company_id", referencedColumnName = "id")
     */
    private $company;
    ...

    /**
     * @param mixed $company
     */
    public function setCompany ($company)
    {
        $this->company = $company;
    }
}

Когда я отправляю форму (которая содержит поля для создания компании и первого пользователя), компания сохраняется в БД, как и первый пользователь, но для company_id пользователя установлено значение NULL. Я должен сделать это, чтобы он заработал (приведенный ниже код находится в службе, предназначенной для управления компаниями):

public function createCompany($company)
    {
    ...
    $company->getUsers()->get(0)->setCompany($company); // <- HERE (btw is there a way to access the first user without using get(0) ?)
    ...

    $this->entityManager->persist($company);
    $this->entityManager->flush();
    }

Я не должен так поступать, правда? я думал что

$user->setCompany($this); 

в addUser сделает это автоматически ...

Где я не прав?

РЕДАКТИРОВАТЬ :

Форма компании: (еще раз, я не помещаю весь код, чтобы он был понятен, я просто публикую полезные строки):

class RegisterCompanyForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name',null,[
            'translation_domain' => 'forms',
            'label' => 'register_company.name.label'
        ])
        ...
        ->add('users', CollectionType::class, [
            'entry_type' => RegisterUserForm::class,
            'entry_options' => array('label' => false),
            'allow_add' => true,
            'by_reference' => false,    
        ])
        ; 
    }
}

Форма пользователя:

class RegisterUserForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('givenName',TextType::class,[
            'translation_domain' => 'forms',
            'label' => 'register_user.givenName.label'
        ])
        ->add('familyName',null,[
            'translation_domain' => 'forms',
            'label' => 'register_user.familyName.label'
        ])
        ...
        ->add('password',null,[
            'translation_domain' => 'forms',
            'label' => 'register_user.password.label'
        ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'App\Entity\User',
        ));
    }
}

Мой шаблон веточки для формы:

{% extends 'layout/layout.html.twig' %}
{% trans_default_domain 'ui' %}

{% block title %}My Form {% endblock %}

{% block content %}
    <div class = "container">
        <div class = "starter-template">
            <h1>{% trans %}title.register{% endtrans %}</h1>
            {{ form_start(form) }}
            {{ form_errors(form) }}
            {{ form_row(form.name) }}
            ...
            {% for user in form.users %}
            {{ form_row(user.givenName) }}
            {{ form_row(user.familyName) }}
            ...
            {{ form_row(user.password) }}
            {% endfor %}
            {{ form_end(form) }}
        </div>
    </div>
{% endblock %}

контролер:

class CompanyController extends Controller
{
    public function inscription(CompanyManager $companyManager, Request 
$request)
    {
        $company = new Company();      
        $user = new User();
        $company->getUsers()->add($user);
        $form = $this->createForm(RegisterCompanyForm::class, $company);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // saving to DB is managed by a service
            $companyManager->createCompany($company);
        }

        return $this->render('views/company/register.html.twig', [
                'form'  => $form->createView()
        ]);
    }
}

в сервисе Менеджер компании:

public function createCompany($company)
    {

        // i'd like to avoid the next line !!! because i think it shouldn't be there...
        $company->getUsers()->get(0)->setCompany($company);

        $this->entityManager->persist($company);
        $this->entityManager->flush();
        return true;
    }

Кстати, я следовал этому руководству, чтобы создать свои формы: https://symfony.com/doc/master/form/form_collections.html

Может у вас есть какая-то ошибка в сущности. Просмотрите этот ответ для отношения manyToOne, и если у вас снова возникнет проблема, введите: stackoverflow.com/questions/49026436/relationships-in-doctri ne /…

l13 19.03.2018 13:59

добавьте и свою пользовательскую сущность, пожалуйста

Preciel 19.03.2018 15:00

сущность пользователя находится чуть ниже сущности компании :) К вашему сведению, я не публиковал весь код для сущностей, только полезные части

sylvain 19.03.2018 15:31

Можете ли вы показать полный код формы и контроллера, в котором она находится? Кроме того, в конструкторе Company вы объявили $users как ArrayCollection: $this->users = new ArrayCollection();?

scandel 19.03.2018 15:52

Я просто добавил формы, контроллер, сервис и ветку. И да, я объявляю $ users как ArrayCollection. Чтобы было ясно: мой код работает, просто я думаю, что мне не нужно вызывать $ company-> getUsers () -> get (0) -> setCompany ($ company); прежде чем настаивать ... мне нравится делать все правильно :)

sylvain 19.03.2018 17:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
5
1 316
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Нам не хватает кода формы, но вот дикая догадка ...

Насколько я понимаю, вы пытаетесь сохранить свой User перед своей компанией. Таким образом, он не может установить company_id, поскольку вы еще не сохранили Company. Попробуйте вместо этого.

public function createCompany($company) {
    // Code folding [...]
    $this->entityManager->persist($company);
    $this->entityManager->flush();
    $this->entityManager->refresh($company); // <== Refreshing persisted eneity to get the new created ID.

    $company->getUsers()->get(0)->setCompany($company);
    // Code folding [...]
}

Внешний ключ хорошо заполняется, когда я делаю: $ company-> getUsers () -> get (0) -> setCompany ($ company); даже если я сделаю это до того, как сохраню $ company. Я хочу избежать этого setCompany, поскольку (я думаю ...) это должно быть сделано внутри addUser () объекта Company

sylvain 19.03.2018 17:44
Ответ принят как подходящий

Что ж, ответ на самом деле довольно очевиден ...

Ошибка была в КомпанияКонтроллер:

$company = new Company();      
$user = new User();
$company->getUsers()->add($user);

должно быть :

$company = new Company();      
$user = new User();
$company->addUser($user);

В исходном коде:

$user->setCompany($this);

никогда не использовался, потому что я добавил пользователя в коллекцию «вручную» ... поэтому связь между созданным пользователем и компанией никогда не устанавливалась. Я ошибся, потому что учебник, которому я следовал (https://symfony.com/doc/master/form/form_collections.html), немного отличался ...

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