Форма Symfony с отображением ManyToMany

Symfony 3.4 Доктрина 1.9

Я нашел много статей об этом. Но ничто не могло решить мою проблему.

У меня есть две сущности User и Company, которые отображаются как Many2Many. Обе сущности должны быть заполнены формой отправки. Поэтому у меня есть следующие типы форм:

ТипРегистрации Клиента

Сюда входит CollectionType с entry_type равным CompanyFormType, который возвращает Company:class

class CustomerRegistrationType extends AbstractType
{

    private $translator;
    private $session;
    public function __construct(TranslatorInterface $translator,Session $session)
    {
        $this->session = $session;
        $this->translator = $translator;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('mandant',HiddenType::class,array('data'=> 
            ->add('newsletter',CheckboxType::class,array('label' => false,'required' => false))
            ->add('company', CollectionType::class, array('entry_type' =>    CompanyFormType::class, 'entry_options' => array('label' => false)));


    }

CompanyFormType

class CompanyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        parent::buildForm($builder, $options);
        $builder->add('telephone', TextType::class,array('required' => false))
            ->add('company_name', TextType::class,array('label' => false,'required' => false))
            ->add('company_supplement', TextType::class,array('label' => 
            ->add('send_info', CheckboxType::class,array('label' => false,'required' => false))
            ->add('send_invoice', CheckboxType::class,array('label' => false,'required' => false))
    }

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

Сопоставление Many2Many

   class User extends BaseUser
    {
        public function __construct()
        {
            parent::__construct();
            $this->company = new ArrayCollection();

        }
    /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Company",inversedBy="users")
         * @ORM\JoinTable(name="user_comp_comp_user",
         *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *      inverseJoinColumns={@ORM\JoinColumn(name="company_id", referencedColumnName="id")}
         * )
         */
        protected $company;

        public function getCompany()
        {
            return $this->company;
        }

        public function setCompany($company)
        {
            $this->company = $company;
            return $this;
        }

        public function addCompany(Company $company)
        {
            if ($this->company->contains($company)) {
                return;
            }
            $this->company[] = $company;
            return $this;
        }

        public function removeCompany(Company $company)
        {
            if (!$this->company->contains($company)) {
                return;
            }
            $this->company->removeElement($company);
            return $this;

        }

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

    /**
     * @var \Doctrine\Common\Collections\Collection|Company[]
     * @ORM\ManyToMany(targetEntity="User",mappedBy="company")
     */

    protected $users;
}

В контроллере я хочу сохранить все данные в разных объектах. Поэтому я делаю:

public function registerAction(Request $request)
    {
        $user = $this->userManager->createUser();

        $form = $this->createForm(CustomerRegistrationType::class,$user);
        $form->handleRequest($request);
        $company = $user->getCompany();
        $company->setSendInvoice(true);
        $company->setSendInfo(true);

        if ($form->isSubmitted()){
            $user->addCompany($company);
            $this->userManager->updateUser($user);
          ....
        }
        return $this->render('Registration/register.html.twig',[
        'form' => $form->createView()
        ]);    
}

Неважно, как я пытаюсь, каждый раз получаю ошибку. В этом примере данные компании пусты. Другие способы противоречат ArrayCollection() из $this->company в User()

User {#907 ▼
  #id: null
  #company: ArrayCollection {#926 ▼
    -elements: []
  }
  #groups: null
  #mandant: null
  #salutation: null
  #first_name: null
  #last_name: null
  #fullname: null
  #created: DateTime @1544539763 {#901 ▶}
  #telephone: null

Обновление: в форме Twig у меня нет доступа к

{{ form_widget(form.company.company_name, {'attr': {'class': 'form-control'}})}}

Ни свойство "company_name", ни один из методов "company_name()", "getcompany_name()"/"iscompany_name()"/"hascompany_name()" или "__call()" не существуют и не имеют общего доступа в классе "Symfony\ Компонент\Форма\Формвиев".

Это происходит перед отправкой формы.


person megadruck    schedule 11.12.2018    source источник
comment
Попробуйте использовать каскад, я не уверен насчет версии 1.9, но текущая похожа на этот документ, скажем doctrine-project.org/projects/doctrine-orm/en/2.6/reference/.   -  person Gabriel Pereira    schedule 11.12.2018
comment
Поскольку $company = $user->getCompany(); приведет к созданию коллекции, вам нужно указать ее как таковую if ($company = $user->getCompany()->first()){ $company->setSendInvoice(true); $company->setSendInfo(true); }. В противном случае вам нужно будет перебрать все компании в коллекции, в зависимости от того, как они добавлены в вашу форму. Вы можете ознакомиться с документацией Symfony в разделе Как встроить коллекцию форм.   -  person Will B.    schedule 11.12.2018
comment
Проблема должна быть где-то еще в Formtype, потому что в Twig Form form.company.plz и все остальные недоступны   -  person megadruck    schedule 12.12.2018


Ответы (1)


Я нашел решение здесь: https://groups.google.com/forum/#!topic/symfony2/DjwwzOfUIuQ

Поэтому я использовал форму на основе массива в контроллере

$form = $this->createFormBuilder()
        ->add('user', CustomerRegistrationType::class, array(
              'data_class' => 'AppBundle\Entity\User'
        ))
        ->add('company', CompanyFormType::class, array(
              'data_class' => 'AppBundle\Entity\Company'
       ))
       ->getForm();

Различные объекты могут быть пойманы следующим образом:

$form->handleRequest($request);
$user = $form->get('user')->getData();
$company = $form->get('company')->getData();

а потом

if ($form->isSubmitted()){
...
$user->addCompany($company);
$this->userManager->updateUser($user);
}

Вот и все

person megadruck    schedule 13.12.2018