@remlin1000
любитель

Как сохранить форму, в которую встроена коллекция другой формы?

Здравствуйте! Уже неделю бьюсь, не могу решить проблему, помогите кто чем может )).

Есть 2 таблицы:
1. Customers (Клиенты)
2. Phone (Телефоны)

Таблица Сustomers связана с таблицей Phone отношением один-ко-многим.

В соответствии с мануалом https://symfony.com/doc/3.4/form/form_collections.html
реализовал встраивание в мою форму коллекции другой формы.

Проблема в том, что при сохранении формы, вылазит ошибка вставки записи в связаную таблицу, так как на момент сохранения, Customer еще не был создан, а таблица Pnone требует customer_id клиента:

An exception occurred while executing 'INSERT INTO phone (phone, description, customer_id) VALUES (?, ?, ?)' with params ["+7 (132) 143-24-12", "Мое примечание", null]:

SQLSTATE[23000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Cannot insert the value NULL into column 'customer_id', table 'CustomersBase.dbo.phone'; column does not allow nulls. INSERT fails.

Как можно решить данную проблему? спасибо!

Ниже привожу сокращенный код:

// src/AppBundle/Entity/Customers.php

/**
 * Customers
 *Заказчики
 * @ORM\Table(name="Customers")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CustomersRepository")
 */
class Customers implements UserInterface
{
    /**
     * @var integer
     *
     * @ORM\Column(name="CustomerID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $customerid;

    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Phone", mappedBy="customer_id", cascade={"persist", "remove", "merge"})
     */
    private $phone;

    public function __construct()
    {
        $this->phone = new ArrayCollection(); //Создаем коллекцию телефонов (связанная таблица phone)
    }

    public function getPhone()
    {
        return $this->phone;
    }

    /**
     * Get customerid
     *
     * @return integer
     */
    public function getCustomerid()
    {
        return $this->customerid;
    }
}


// src/AppBundle/Entity/Phone.php

**
 * Phone
 *
 * @ORM\Table(name="phone", indexes={@ORM\Index(name="IDX_444F97DD9395C3F3", columns={"customer_id"})})
 * @ORM\Entity
 */
class Phone
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \AppBundle\Entity\Customers
     *
     * @ORM\ManyToOne(targetEntity="Customers", inversedBy="customerid")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="customer_id", referencedColumnName="CustomerID")
     * })
     */
    private $customer_id;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return \AppBundle\Entity\Customers
     */
    public function getCustomerId()
    {
        return $this->customer_id;
    }

    /**
     * @param \AppBundle\Entity\Customers $customer
     */
    public function setCustomerId(\AppBundle\Entity\Customers $customer)
    {
        $this->customer_id = $customer;
    }
}


// src/AppBundle/Form/CustomerType.php

class CustomerType extends AbstractType
{
   public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //....
        $builder
            ->add('phone',CollectionType::class, array(
                'entry_type' => PhoneType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'entry_options' => array(
                    'required' => false,
                    'label' => false
                )
            ));
          //....
   }
    
public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Customers'
        ));
    }


// src/AppBundle/Form/PhoneType.php

class PhoneType extends AbstractType
{


    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('phone', null);
        $builder->add('description', null);
        $builder->add('customerId', HiddenType::class);
    }

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


// src/AppBundle/Controller/CustomersController.php

class CustomersController extends Controller
{
    public function indexAction(Request $request)
    {

        $customer = new Customers();
        //Добавляем пустой телефон, чтобы отобразить его в форме
        $phone = new Phone();
        $customer->getPhone()->add($phone);

        $form = $this->createForm('AppBundle\Form\CustomerType', $customer);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($customer);
            $em->flush();
     }
}

}
  • Вопрос задан
  • 130 просмотров
Решения вопроса 1
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
По вашей же ссылке предлагается решение:
// src/AppBundle/Form/CustomerType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
    //....
    $builder
        ->add('phones',CollectionType::class, array(
            'by_reference' => false,
            // ...
        ));
    //....
}


class Customers implements UserInterface
{
    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Phone", mappedBy="customer_id", cascade={"persist", "remove", "merge"})
     */
    private $phones; // Это же коллекция, нужно множественное число, чтобы работали adder и remover

    public function addPhone(Phone $phone)
    {
        $phone->setCustomer($this);
        $this->phones->add($phone);
    }

    public function removePhone(Phone $phone)
    {
        $phone->setCustomer(null);
        $this->phones->removeElement($phone);
    }
}


// src/AppBundle/Form/PhoneType.php
// $builder->add('customerId', HiddenType::class); // не нужен
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы