Необходимо дать возможнсть пользователям при создании счета добавлять позиции. Счет - entity Invoice
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Invoice
*
* @ORM\Table(name="invoices")
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\InvoiceRepository")
* @ORM\EntityListeners({ "AppBundle\Entity\Listener\InvoiceListener" })
*
* @UniqueEntity(fields={"number"}, message="Такой номер уже существует")
*/
class Invoice
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Разбивка счета
*
* @ORM\OneToMany(targetEntity="InvoiceLine", mappedBy="invoice", cascade={"persist", "remove"})
*
* @var InvoiceLine
*/
protected $lines;
public function addInvoiceLine(InvoiceLine $line) {
// $line->addInvoice($this);
$this->lines->add($line);
}
}
Позиции счета InvoiceLine
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* InvoiceLine
*
* @ORM\Table(name="invoices_lines")
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\InvoiceLineRepository")
*/
class InvoiceLine
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Счет
*
* @ORM\ManyToOne(targetEntity="Invoice", inversedBy="lines")
* @ORM\JoinColumn(name="invoice_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*
* @Assert\NotBlank(message="Поле обязательно для заполнения")
*
* @var \AppBundle\Entity\Invoice
*/
protected $invoice;
/**
* @ORM\Column(type="text", nullable=false)
*
* @Assert\NotBlank(message="Поле обязательно для заполнения")
*/
protected $description;
/**
* @ORM\Column(type="decimal", precision = 20, nullable=false)
*
* @Assert\NotBlank(message="Поле обязательно для заполнения")
*/
protected $cost;
Форма счета:
<?php
namespace AppBundle\Form\Type;
use AppBundle\Entity\InvoiceLine;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class InvoiceType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('number')
->add('createDate')
->add('status', 'choice', array(
'choices' => array(
'0' => 'Не оплачен',
'1' => 'Оплачен',
'2' => 'Отменен',
)
))
->add('client')
->add('lines', 'collection', array(
'type' => new InvoiceLineType(),
'allow_add' => true,
// 'delete_empty' => true,
// 'prototype' => true,
// 'allow_delete' => true,
'by_reference' => false,
));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\Invoice'
)
);
}
/**
* @return string
*/
public function getName()
{
return 'appbundle_invoice';
}
}
Форма позиции:
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class InvoiceLineType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description')
->add('cost')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\InvoiceLine'
));
}
/**
* @return string
*/
public function getName()
{
return 'invoiceline';
}
}
Контроллер
namespace AppBundle\Controller;
use AppBundle\Entity\InvoiceLine;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use AppBundle\Entity\Invoice;
use AppBundle\Form\Type\InvoiceType;
use JMS\DiExtraBundle\Annotation as DI;
/**
* @Route("/admin/invoice")
*/
class InvoiceController extends Controller
{
/**
* @DI\Inject("doctrine.orm.entity_manager")
*
* @var \Doctrine\ORM\EntityManager
*/
private $em;
/**
* @Route("/add", name="invoice_add")
* @Template()
*
* @var Request $request
* @return array
*/
public function invoiceAddAction(Request $request)
{
$invoice = new Invoice();
$form = $this->createForm(new InvoiceType(), $invoice);
$form->handleRequest($request);
if ($form->isValid()) {
$this->em->persist($invoice);
$this->em->flush();
$this->addFlash('success', 'Счет добавлен');
return $this->redirect($this->generateUrl('invoice_list'));
}
return array( 'form' => $form->createView() );
}
}
вывод формы:
{% extends is_ajax ? 'AppBundle::layout_ajax.html.twig' : 'AppBundle::layout.html.twig' %}
{% block content %}
<form class="form-horizontal" method="post" action="{{ path('invoice_edit', {'id': client.id}) }}">
{{ form_errors(form) }}
{{ form_widget(form) }}
<button type="submit" class="btn btn-primary">Сохранить</button>
</form>
{% endblock content %}
В результате получаю форму счета с кнопкой добавить line при нажатии на которую появляется вложенная форма позиции(за добавление html формы позиции отвечает mopabootstrapbundle). При внесении данных - ошибка
An exception occurred while executing 'INSERT INTO invoices_lines (description, cost, invoice_id) VALUES (?, ?, ?)' with params ["32", 234, null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'invoice_id' cannot be null
Почему возникает ошибка - у позиции не хватет id счета. Как сделать привязку? При работе опирался на
эту инструкцию.