Answer the question
In order to leave comments, you need to log in
How to make nested forms in Symfony2?
It is necessary to enable users to add positions when creating an account. Account - 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);
}
}
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 %}
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
Answer the question
In order to leave comments, you need to log in
public function addLine(InvoiceLine $line) {
$line->setInvoice($this);
$this->lines->add($line);
}
You probably need some kind of hidden field in InvoiceLineType, which will contain the invoice id
// $line->addInvoice($this); If you uncomment, will it be the same? And in place of the controller Form Type is displayed.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question