Symfony 2 Quiz style - symfony-2.3

I want to make a quiz(really simple one) for my student. I have 2 entity one question and one answer with a relation onetomany frome answer entity.
I want to be able to write the questions for a tex X and put all of them in a page with a field answer.
Exemple:
1) question 1
<input name question1>
2) question 2
<input name question2>
I did this for the moment:
public function newAction() {
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('AdminQuizBundle:Question')->findAll();
$questions = array();
$forms = array();
foreach ($entities as $question) {
$entity = new Reponse();
$form = $this->createForm(new ReponseType(), $entity);
$questions[] = $question;
$forms[] = $form->createView();
}
return array(
'entity' => $entity,
'form' => $forms,
'questions' => $questions,
);
}
it works but went i try to save just the last one did

Related

Symfony 3 : add a field to a already submitted form

after looking on other topics i haven't resolved my problem, i'm looking to add the field user_id to the form (as the user won't choose it) but symfony return me "Call to a member function addEventListener() on string"
here is my code :
if ($form->isSubmitted() && $form->isValid()) {
$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$data['user_id'] = '2';
$event->setData($data);
});
$em = $this->getDoctrine()->getManager();
$em->persist($deplacement);
$em->flush($deplacement);
return $this->redirectToRoute('deplacement_show', array('id' => $deplacement->getId()));
}
Sure this is the good aproach? Maybe is better for you to write a method to update or create $deplacement, and pass 2 argoument: the $data variable from the form and the user_id, like this:
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$userId = 2;
$formData->userId = $userId;
$deplacement->update($formData);
$em->persist($deplacement);
$em->flush($deplacement);
return $this->redirectToRoute('deplacement_show', array('id' => $deplacement->getId()));
}
Also I think you dont need the event listener. Why are you using it?

Symfony3 : multi-steps form and flush after forward

I have a form to add a new prescriber in my database. The first step consists in informing the various informations about the prescriber.
Then, I check if there are similar prescribers before adding it (2nd step with a 2nd form) and if there are, I ask the user to confirm.
In short, I have a 1-step form or a 2-steps form, depending on duplicates.
I tried with CraueFormFlowBundle but I don't know how to implement my conditional second step. My tests were inconclusive. So I decided to use forward method in my controller, and I like it !
But, I can't manage to flush my prescriber at the end of the 2nd step (after forwarding), I have this error : Unable to guess how to get a Doctrine instance from the request information for parameter "prescriber".
addAction (= step 1)
/**
* Add a new prescriber
*
* #Route("/prescribers/add", name="prescriber_add")
*/
public function addAction(Request $request) {
$em = $this->getDoctrine()->getManager();
$rp = $em->getRepository('AppBundle:Prescriber');
$p = new Prescriber();
// build the form
$form = $this->createForm(AddPrescriberType::class, $p);
// handle the submit
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
# search if a prescriber already exists
$qb = $rp->createQueryBuilder('p');
$qb->where($qb->expr()->eq('p.rpps', ':rpps'))
->orWhere($qb->expr()->andX(
$qb->expr()->like('p.lastname', ':name'),
$qb->expr()->like('p.firstname', ':firstname')
))
->setParameter('rpps', $p->getRpps())
->setParameter('name', '%'.$p->getLastname().'%')
->setParameter('firstname', '%'.$p->getFirstname().'%');
$duplicates = $qb->getQuery()->getArrayResult();
# there are duplicates
if (!empty($duplicates)) {
$em->persist($p);
// confirm the addition of the new prescriber
$params = array('prescriber' => $p, 'duplicates' => $duplicates);
$query = $request->query->all();
return $this->forward('AppBundle:Prescriber:addConfirm', $params, $query);
} else {
$em->persist($p); # save the prescriber
$em->flush(); # update database
$this->addFlash('p_success', 'The prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
}
// show form
return $this->render('prescribers/form-step1.html.twig', array(
'form' => $form->createView()
));
}
addConfirmAction (= step 2)
/**
* Confirm addition of a new prescriber
*
* #Route("/prescribers/add/confirm", name="prescriber_add_confirm")
*/
public function addConfirmAction(Prescriber $prescriber, $duplicates, Request $request) {
$em = $this->getDoctrine()->getManager();
$form = $this->createFormBuilder()->getForm();
if ($form->handleRequest($request)->isValid()) {
$em->persist($prescriber);
$em->flush();
$this->addFlash('p_success', 'Prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
// show confirm page
return $this->render('prescribers/form-step2.html.twig', array(
'h1_title' => 'Ajouter un nouveau prescripteur',
'form' => $form->createView(),
'p' => $prescriber,
'duplicates'=> $duplicates
));
}
I think the problem comes from the fact that I have 2 forms submissions...
I found a solution by using the session.
(I know it's not a perfect way but I didn't find other one)
For Symfony 3.3.*
use Symfony\Component\HttpFoundation\Session\SessionInterface;
public function addAction(Request $request, SessionInterface $session) {
// [...]
# there are duplicates
if (!empty($duplicates)) {
$data = $form->getData();
$session->set('prescriber', $data);
$session->set('duplicates', $duplicates);
return $this->forward('AppBundle:Prescriber:addConfirm');
// [...]
}
public function addConfirmAction(Request $request, SessionInterface $session) {
$em = $this->getDoctrine()->getManager();
$p = $session->get('prescriber');
$duplicates = $session->get('duplicates');
// empty form with only a CSRF field
$form = $this->createFormBuilder()->getForm();
if ($form->handleRequest($request)->isValid()) {
$em->persist($p);
$em->flush();
$this->addFlash('p_success', 'The prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
// show confirm page
return $this->render('prescribers/form-step2.html.twig', array(
'form' => $form->createView(),
'prescriber'=> $p,
'duplicates'=> $duplicates
));
}

Symfony 2 Choice Field Default Value

I have this field in my form:
->add('taskOwner', null, array(
'label' => $this-> translator ->trans( 'tasks.index.responsible' , array() , 'crm' )))
Symfony recognize it as Choice Type (it's have foreign key to another table, with users). Now i want to set the default value on the logged user. How I can do that ? I tried in my controller create new entity of my type, set taskOwner into it and then by SetData put in into form, like this:
$entity = new Tasks();
$tasksForm = $this->createForm(new TasksType($translator), $entity);
$userId = $this->get('security.context')->getToken()->getUser()->getId();
$user = $this->getDoctrine()->getRepository('CloudAdmBundle:AdmUser')->find($userId);
$task = new Tasks();
$task->setTaskOwner($user);
$tasksForm->setData($task);
To clear everything, definition of setter:
public function setTaskOwner(\Cloud\AdmBundle\Entity\AdmUser $taskOwner = null)
{
$this->taskOwner = $taskOwner;
return $this;
}
Do it before you create the form:
$userId = $this->get('security.context')->getToken()->getUser()->getId();
$user = $this->getDoctrine()->getRepository('CloudAdmBundle:AdmUser')->find($userId);
$entity = new Tasks();
$entity->setTaskOwner($user);
$tasksForm = $this->createForm(new TasksType($translator), $entity);

Pass the current querystring parameters through symfony forms

Our application uses several webforms and some of them only should add or change several parameters in the querystring. As example there are a filter form and a form for the list order (just a dropdown).
Both are indipendant, but if I change one, I have to pass the current querystring parameters with the new request. How can I manage it?
This is just one of the possible solutions, it will depend on your implementation if it would help you.
<?php
$allowedQueryParams = array('param1', 'param2', 'param3');
// I'll fake a request here
$request = new Request(array('param2' => 'foo', 'param3' => 'bar', 'param4' => 'dummy'));
$formFactory = Forms::createFormFactoryBuilder()->getFormFactory();
$formBuilder = $formFactory->createBuilder();
$formBuilder->add('param1', 'text');
$data = array();
foreach ($allowedQueryParams as $param) {
if ($request->query->has($param)) {
// Add the query param as hidden field to you form
$formBuilder->add($param, 'hidden');
$data[$param] = $request->query->get($param);
}
}
$formBuilder->setData($data);
$form = $formBuilder->getForm();
So basically you add hidden fields with the current query parameters.
Edit:
But if you would have many forms, you might want to do this with an EventSubscriber
An alternative approach would be to combine the two forms into one master form.
From your controller:
$formData = array(
'filterParams' => array(), // Default filter parameters
'listOrderParams' => array(), // Default list order parameters
);
$form = $this->createFormBuilder($task)
->add('filterParams', new FilterFormType())
->add('listOrderParams', new ListOrderFormType())
->add('update', 'submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$formData = $form->getData();

Symfony2 Form Entity Update

Can anyone please show me a specific example of a Symfony2 form entity update? The book only shows how to create a new entity. I need an example of how to update an existing entity where I initially pass the id of the entity on the query string.
I'm having trouble understanding how to access the form again in the code that checks for a post without re-creating the form.
And if I do recreate the form, it means I have to also query for the entity again, which doesn't seem to make much sense.
Here is what I currently have but it doesn't work because it overwrites the entity when the form gets posted.
public function updateAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$testimonial = $em->getRepository('MyBundle:Testimonial')->find($id);
$form = $this->createForm(new TestimonialType(), $testimonial);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
echo $testimonial->getName();
if ($form->isValid()) {
// perform some action, such as save the object to the database
//$testimonial = $form->getData();
echo 'testimonial: ';
echo var_dump($testimonial);
$em->persist($testimonial);
$em->flush();
return $this->redirect($this->generateUrl('MyBundle_list_testimonials'));
}
}
return $this->render('MyBundle:Testimonial:update.html.twig', array(
'form' => $form->createView()
));
}
Working now. Had to tweak a few things:
public function updateAction($id)
{
$request = $this->get('request');
if (is_null($id)) {
$postData = $request->get('testimonial');
$id = $postData['id'];
}
$em = $this->getDoctrine()->getEntityManager();
$testimonial = $em->getRepository('MyBundle:Testimonial')->find($id);
$form = $this->createForm(new TestimonialType(), $testimonial);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// perform some action, such as save the object to the database
$em->flush();
return $this->redirect($this->generateUrl('MyBundle_list_testimonials'));
}
}
return $this->render('MyBundle:Testimonial:update.html.twig', array(
'form' => $form->createView()
));
}
This is actually a native function of Symfony 2 :
You can generate automatically a CRUD controller from the command line (via doctrine:generate:crud) and the reuse the generated code.
Documentation here :
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_doctrine_crud.html
A quick look at the auto-generated CRUD code by the Symfony's command generate:doctrine:crudshows the following source code for the edit action
/**
* Displays a form to edit an existing product entity.
*
* #Route("/{id}/edit", name="product_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Product $product)
{
$editForm = $this->createForm('AppBundle\Form\ProductType', $product);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('product_edit', array('id' => $product->getId()));
}
return $this->render('product/edit.html.twig', array(
'product' => $product,
'edit_form' => $editForm->createView(),
));
}
Note that a Doctrine entity is passed to the action instead of an id (string or integer). This will make an implicit parameter conversion and saves you from manually fetching the corresponding entity with the given id.
It is mentioned as best practice in the Symfony's documentation