Я знаю, что в 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
добавьте и свою пользовательскую сущность, пожалуйста
сущность пользователя находится чуть ниже сущности компании :) К вашему сведению, я не публиковал весь код для сущностей, только полезные части
Можете ли вы показать полный код формы и контроллера, в котором она находится? Кроме того, в конструкторе Company вы объявили $users как ArrayCollection: $this->users = new ArrayCollection();?
Я просто добавил формы, контроллер, сервис и ветку. И да, я объявляю $ users как ArrayCollection. Чтобы было ясно: мой код работает, просто я думаю, что мне не нужно вызывать $ company-> getUsers () -> get (0) -> setCompany ($ company); прежде чем настаивать ... мне нравится делать все правильно :)






Нам не хватает кода формы, но вот дикая догадка ...
Насколько я понимаю, вы пытаетесь сохранить свой 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
Что ж, ответ на самом деле довольно очевиден ...
Ошибка была в КомпанияКонтроллер:
$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), немного отличался ...
Может у вас есть какая-то ошибка в сущности. Просмотрите этот ответ для отношения manyToOne, и если у вас снова возникнет проблема, введите: stackoverflow.com/questions/49026436/relationships-in-doctri ne /…