I'm beginner on symfony and I have to use the collection form to make a site to reserve tickets for a show.
The interface is simple, The user select the number of tickets he wants, then it display as much form prototype (name and surname input) as tickets required.
This part works well for me.
I have 2 table "reservations" and "ticket" in mysql and I would like to get this render after submiting the form:
Table reservation :
Reservation id = 1
Table ticket:
Ticket id="1" name="thomas", surname="good", reservation_id="1"
Ticket id="2" name="laura", surname="senior", reservation_id="1"
But when I submit my form, I get +1 reservation in my table but no data in my ticket table.
class AdvertController extends Controller
{
public function formAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$reservation = new Reservations();
$form = $this->createForm(new ReservationsType(), $reservation, array(
'action' => $this->generateUrl('louvre_pages_homepage'),
'method' => 'POST',
));
$form->handleRequest($request);
$em->persist($reservation);
$em->flush();
return $this->render('LouvrePagesBundle:Pages:index.html.twig', array(
'form' => $form->createView(),
));
}
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tickets', CollectionType::class, array(
'entry_type' => TicketType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'prototype' => true,
)
)
->add('save', 'submit', array(
'attr' => array(
'class' => 'btn btn-lg btn-success'
)
));
}
public function getName()
{
return 'reservations';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Louvre\PagesBundle\Entity\Reservations',
));
}
Is my controller right ?
I see 2 problems in the formAction:
there is no call to $em->flush(); anywhere
you are always calling $em->persist($reservation); regardless of the form validation state
Try doing it this way:
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($reservation);
$em->flush();
// now redirect, add flash message, etc.
}
See http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Related
for a few days I am blocked, if someone can help me with the good practice, I explain:
I want to retrieve data from the database: entity (expression_besoin) contains the information of a purchase with ref , requester ... and the entity besoin_article contains the items products in the previous entity, there is a OneToMany relationship between the two entities.
the objective is to retrieve the several expression needs of articles in a form in order to modify whether the quantities are necessary or to delete them, then to be able to generate a PDF file which contains all the needs and the articles which correspond to them.
Controller :
/**
* #Route("/extraire_commandes", name="export_commandes", methods={"GET","POST"})
*/
public function exportCommandes(ExBesoinRepository $exBesoinRepository, Request $request): Response
{
$datas = new FiltreBesoin();
$form = $this->createForm(FiltreBesoinType::class, $datas);
$form->handleRequest($request);
$exBesoin = $exBesoinRepository->exportCommande($datas);
$valueFournisseur = $form['fournisseur']->getData();
$formExport = $this->createFormBuilder(array('besoin' => $exBesoin));
$formExport->add('besoin', CollectionType::class, array(
'entry_type' => ExBesoinToCommandeType::class,
));
$formExport = $formExport->getForm();
$formExport->handleRequest($request);
$formValue = $formExport->getData();
if ($formExport->isSubmitted() && $formExport->isValid()) {
$html = $this->renderView('admin/besoins/epicerie/exportPdf.html.twig', [
'besoins' => $formValue,
]);
$html .= '<link rel="stylesheet" href="/build/css/app.css"> ';
$html .= '<script src="/build/vendors~js/app.js"></script><script src="/build/runtime.js"></script><script src="/build/vendors-node_modules_popperjs_core_lib_index_js-node_modules_symfony_stimulus-bridge_dist_ind-f4bfca.js"></script>';
$name = 'test';
$options = new Options();
$options->set('isHtml5ParserEnabled', true);
$options->set('isRemoteEnabled', true);
$dompdf = new Dompdf($options);
$dompdf->loadHtml($html);
// (Optional) Setup the paper size and orientation
$dompdf->setPaper('A4', 'portrait');
// Render the HTML as PDF
$dompdf->render();
// Output the generated PDF to Browser
$dompdf->stream($name, array('Attachment' => 0));
return new Response('', 200, [
'Content-Type' => 'application/pdf',
]);
}
return $this->render('admin/besoins/epicerie/export.html.twig', [
'besoins' => $exBesoin,
'form' => $form->createView(),
'valueFournisseur' => $valueFournisseur,
//'idBesoin' => $idBesoin,
'formExport' => $formExport->createView(),
'valu'=> $formValue
]);
}
FormType
class ExBesoinToCommandeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('besoinArs', CollectionType::class, [
'entry_type' => BesoinArToCommandeType::class,
'allow_delete' => true,
//'allow_add' => false,
'prototype' => true,
'by_reference' => false,
'delete_empty' => true,
'entry_options' => [
'label' => true,
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ExBesoin::class,
]);
}
public function getBlockPrefix()
{
return 'ExBesoinToCommandeType';
}
}
class BesoinArToCommandeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('article', EntityType::class, [
'class' => Article::class,
'label' => false,
'attr' =>[
'class' => 'arSelect form-control-sm',
'data-live-search' => 'true',
],
'placeholder' => 'Selectionner un article ',
'query_builder' => function (EntityRepository $er) {
$qb = $er->createQueryBuilder('a')
->innerJoin('a.category', 'c')
->where('c.is_legume = 0')
;
return $qb;
},
'group_by' => function (Article $article) {
return $article->getCategory()->getLibele();
}
])
->add('quantity', TextType::class, [
'label' => ' ',
'attr' =>[
'class' => 'quantity form-control-sm'
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => BesoinAr::class,
]);
}
public function getBlockPrefix()
{
return 'BesoinArToCommandeType';
}
}
Until I get my data back without problem, the getData() of the form contains all my data before the submit, but when I validate to generate my pdf file, it does not contain all the data. I use a filter system that allows me to select the expressions of need between two dates, by requester or by supplier, and the problem is linked to this filter because when I generate the pdf of the data without filter it works but when I filter my data this is where my data changes and I don't recover the filtered data, I will be grateful if someone unblocks me or tell me where the problem comes from.
I've been looking for a solution for hours. I'am working with Symfony 3.2.
I'am using Symfony Forms in order to display a data-table (with different filter chosen in the form) with Ajax => No submit button.
I can access to different result of data-table to view more information.
What i want is that when i leave the detail page by clicking on a button and come back on the research page, that i could keep in history all filters that i have chosen.
i wanted use session but actually, it seems has 0 impact. Below is some codes.
Controller:
public function indexAction(Request $request)
{
$form = $this->createSearchForm();
$request->getSession()->set('form_data', $form->getData());
$form->handleRequest($request);
$form->setData($request->getSession()->get('form_data'));
$this->datatable($form->getData());
return $this->render('backend/jobOffer/index.html.twig', [
'form' => $form->createView()
]);
}
FormType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('publicationState', ChoiceType::class, [
'label' => 'backend.job_offer.publication_state',
'required' => false,
'choices' => JobOffer::getPublicationStateChoices(),
'choice_translation_domain' => 'choices',
])
->add('job', Select2EntityType::class, [
'label' => 'backend.job',
'required' => false,
'class' => 'AppBundle:Job',
'text_property' => 'label',
'remote_route' => 'job_autocomplete',
])
->add('ids', HiddenType::class, [
'required' => false,
])
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'csrf_protection' => false,
'method' => 'GET',
]);
}
I have a problem, there is a EntityType (or Select2EntityType) field named "job" in my form builder and i can't get the content of this field in my session. This field shows a autocomplete data-list after typing 2 letters, and we can choose one of job.
and also, when i refresh the page, i lose all filters, but i am supposed to store them in session ?
Thanks in advance for your help,
Yes you can use $form->getData() but to do that you need to do this according to the doc here with using if ($form->isSubmitted() && $form->isValid()) { among others.
I can not get value from EntityType. I have last version 3.3.6.
class BuildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array
$options)
{
$builder
->add('title', TextType::class)
->add('save', SubmitType::class, array('label' => 'Create Post'))
->add('team', CollectionType::class, array(
// each entry in the array will be an "email" field
'entry_type' => TeamType::class,
// these options are passed to each "email" type
'entry_options' => array(
'attr' => array('class' => 'form-control'),
),
'label' => false,
'allow_add' => true,
'prototype' => true,
'mapped' => false
));
}
}
class TeamType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array
$options)
{
$builder
->add('name', EntityType::class, array(
'placeholder' => 'Choice a champ',
'required' => true,
'class' => 'AppBundle:Champions',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'attr' => array('class' => 'dropdown'),
));
}
I tried all but i cannot take value of 'name' of TeamType. After submission form, i do
foreach ($form["team"]->getData() as $value) {
'name' => $value['name']
but the value is empty. If i try dump request and the value is there. The other values i can get it and save in Database. Only EntityType i can not.
Someone know how do?
EntityType returns as the object. You should use model getter functions.
$form->get('name')->getData()->getId(); // getName() vs..
Here is a similar example.
symfony how get selected data from select
I suppose that you are using ManyToOne relationship.
With AJAX
if you are trying get data after submitted, You can do this first in your view:
$('#elementWhereYouAreTEAMType').find('input').each(function (i,v) {
var valTeam = $(this).val(); //take value
// adding data, create an associative array.
formData.append("team["+ i +"]", valTeam);
});
You must put formData like data argument to ajax JQuery
Now, server side:
public function createTeamNow(Request $request) {// ajax
$teams = $request->request->get('team'); // getting array
if(!is_null($teams)) {// if user added team
foreach ($teams as $team) {
// dump($team);
//create an instance for each element, it does not replace a data with the above
$teamType = new TeamType();
$teamName->setName($team);
$this->em->persist($teamType);
}
}
}
Without AJAX
/**
* #Route("/slim/1" , name="data_x")
*/
public function slimExampleAction(Request $request)
{
$form = $this->createForm(TeamType::class);
$form->handleRequest($request);
if ($form->isSubmitted() /*&& $form->isValid()*/) {
// When you've ManyToOne relationship, that field returns ArrayCollection class, it has several method to get data on differents ways, iterate with it, for example toArray is one
$data = $form->getData();
dump($data->getDescription()->toArray());die;
}
return $this->render('AppBundle:view.html.twig', array(
'form' => $form->createView(),
));
}
I have a form that collects data from two related entities 'Jobs' and 'Scope'. Jobs data adds successfully to the database, but i can't get the scope entity to add which also requires the unique ID that was created from the jobs entry. I'm using doctrine by the way.
Here is jobsType:
class jobsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('jobNumber', null, array('label' => 'Job Number','attr' => array('placeholder'=>'Code used for job')))
->add('description', null, array('label' => 'Job Description',))
;
$builder->add('scopes', new scopeType())
;
}
public function getName()
{
return 'jobs';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Baker\TimeSlipBundle\Entity\Jobs',
));
}
}
Here is scopeType
class scopeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', 'entity', array('label' => 'Scope', 'required' => false,
'class' => 'BakerTimeSlipBundle:Scope',
'query_builder' => function(EntityRepository $er){
return $er->createQueryBuilder('s')
->orderBy('s.description', 'asc');
},
'property' => 'description',
'multiple' => false,
'expanded' => false,
'empty_value' => false,
'attr' => array('class' => 'form-inline'),
'label_attr' => array('class' => 'required')
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Baker\TimeSlipBundle\Entity\Scope',
));
}
public function getName()
{
return 'scope';
}
}
Here is my controller, i think the problem here is that i'm not passing the scope() instance to the form builder. Which i'm not sure how to do. The entity is mapped correctly.
class JobsController extends Controller
{
public function indexAction($limit, Request $request)
{
$jobs= new Jobs();
$scope = new Scope();
$fname=$limit;
$form = $this->createForm(new JobsType(),$jobs, array(
'method' => 'POST',
));
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($jobs);
$em->persist($scope);
$em->flush();
return $this->redirectToRoute('company',array ('limit' =>'Job Submitted Successfully'));
}
return $this->render(
'BakerTimeSlipBundle:Jobs:index.html.twig',
array('fname' => $fname,
'form' => $form->createView()
)
);
}
}
}
Any help here would be greatly appreciated. Below is listed the error message when I try to enter the scope:
An exception occurred while executing 'INSERT INTO Scope (description, jobsId, jobsid) VALUES (?, ?, ?)' with params [null, null, null]:
SQLSTATE[42000]: Syntax error or access violation: 1110 Column 'jobsId' specified twice
The problem here is the $jobs object you link to your form has no relation with the $scope object. So when you try to persist $jobs, Doctrine has no idea $scope it had to persist.
Just try this :
$jobs= new Jobs();
$scope = new Scope();
$jobs->setScope($scope);
Then, in your Jobs entity, on the annotation above $scopes, make sure you have cascade={"persist"} (but you must already have it because Doctrine tries to persist, and that's where the error is thrown), and you should be good to go.
Hope this helps
I'm on a problem related to a Symfony2 application which i'm building. The problem concerns an article (News) linked to one or many pictures (Illustration). It seems pretty simple. But i'm stacking on the controller which should persist the News, the Illustration and uploading the picture file.
My News form type:
namespace Fcbg\NewsBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class NewsType extends AbstractType
{
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
->add('date', 'date')
->add('titre', 'text')
->add('contenu', 'textarea')
->add('publication', 'checkbox', array('required' => false))
->add('type', 'entity', array( 'class' => 'FcbgNewsBundle:Illustration', 'property' => 'value', 'multiple' => true ));
}
public function getName()
{
return 'News';
}
}
My picture(s) form type:
namespace Fcbg\NewsBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class IllustrationType extends AbstractType
{
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
->add('file', 'file');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Fcbg\NewsBundle\Entity\Illustration',
'cascade_validation' => true,
));
}
public function getName()
{
return 'News';
}
}
My controller action:
public function addAction()
{
//link works properly I think
$news = new News();
$illustration = new Illustration();
$illustration->setNews($news);
$news->addIllustration($illustration);
$form = $this->createForm(new NewsType(), $news);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$doctrine = $this->getDoctrine();
$newsManager = $doctrine->getManager();
$newsManager->persist($news);
$newsManager->persist($illustration);
$newsManager->flush();
return $this->redirect(...);
}
}
return $this->render('base.html.twig',
array(
'content' => 'FcbgNewsBundle:Default:formulaireNews.html.twig',
'form' => $form->createView(),
'name' => "add a news"
)
);
}
The error i get on the execution:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
The problem here is that my entity gets a method called "getIllustrations()" which returns logically an arrey of Illustration. So i'm not able to understand this error/question. I assume that my "illustration should be a file field and not a choice field...
Any idea about how i can go further? thx a lot!
I think the problem is that you are using the 'entity' form field here:
->add('type', 'entity', array( 'class' => 'FcbgNewsBundle:Illustration', 'property' => 'value', 'multiple' => true ));
and this type of form field acts as a choice and it's used to work with elements created in the database. You can see this in http://symfony.com/doc/current/reference/forms/types/entity.html
A possible solution could be use the "prototype" like here http://symfony.com/doc/current/cookbook/form/form_collections.html#cookbook-form-collections-new-prototype
where you could have:
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
->add('date', 'date')
->add('titre', 'text')
->add('contenu', 'textarea')
->add('publication', 'checkbox', array('required' => false))
->add('type', 'collection', array(
'type' => new IllustrationType(),
'allow_add' => true,
));
}
I hope that this be useful for you.
Kind regards.
So, the code which I was talking about:
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
->add('date', 'date')
->add('titre', 'text')
->add('contenu', 'textarea')
->add('publication', 'checkbox', array('required' => false))
->add('illustrations', 'collection', array(
'type' => new IllustrationType(),
'allow_add' => true
));
}