Symfony & Doctrine: persisting a many to one entity on an embedded form collection - php

Currently in a bit of a pickle. I have 2 entities: Main and Sub, it is a OneToMany relationship (one main can have many subs) I made a collection of form embedded together. I first had a search form where a user can search a Main by one of its attributes, then it sends them to a page where there is a form with the searched Main, its attributes listed on the form but is disabled so users cannot edit them, and the enabled fields are from the embedded Sub form which users need to enter in for submission.
1) User searches Main by its attribute, i.e. "pono" (PO number)
2) User is redirected to a page that shows the row that he/she searched for with the listed (pono), (cano), (bano) - it is disabled so it cannot be edited
3) Enabled fields are empty and users must enter the information that would be submitted into the Sub entity.
In my Main entity
/**
* #var Sub
* #ORM\OneToMany(targetEntity="Sub", mappedBy="mainId")
*/
protected $sub;
public function __construct() {
$this->sub = new ArrayCollection();
}
And my Sub entity:
/**
* #var integer
*
* #ORM\Column(name="main_id", type="integer")
*/
protected $mainId;
/**
* #ORM\ManyToOne(targetEntity="Main", inversedBy="sub", cascade={"persist"})
* #ORM\JoinColumn(name="main_id", referencedColumnName="id")
*/
protected $main;
In my Main form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pono', 'text', array(
'label' => 'PO: ',
'disabled' => true
))
->add('cano','text', array(
'label' => 'CA: ',
'disabled' => true
))
->add('bano', 'text', array(
'label' => 'BA: ',
'disabled' => true
))
->add('sub', 'collection', array('type' => new SubType()));
}
In my Sub form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('qty','integer', array(
'label' => 'Qty: '
))
->add('location','text', array(
'label' => 'Location: '
))
->add('priority','text', array(
'label' => 'Priority: '
));
}
So on my controller
public function submitItemAction(Request $request, $pono) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ItemBundle:Main')
->findOneByPono($pono);
$cano = $entity->getCano();
$bano = $entity->getBano();
$main = new Main();
$main->setPono($pono);
$main->setCano($cano);
$main->setBano($bano);
$sub = new Sub();
$sub->setMain($main);
$main->getSub()->add($sub);
$form = $this->createForm(new MainType(), $main, array(
'method' => 'POST'
))
->add('submit','submit');
$form->handleRequest($request);
if($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($sub);
$em->flush();
return $this->redirect($this->generateUrl('success'));
}
Now when this is submitted, it's submitting BOTH Main and Sub. It's giving me a duplicate Main and the newly added Sub. I know it is what it's supposed to do, but I need it to only submit the Sub. I tried retrieving the id from Main with a $mainid = $entity->getId(); and putting it into $sub->setMainId($mainid) and I keep getting the error message that main_id cannot be null.
Any takers?
Edit: Twig template:
{{ form_start(form) }}
{{ form_label(form.pono) }}
{{ form_widget(form.pono) }} <br>
{{ form_label(form.cano) }}
{{ form_widget(form.cano) }}<br>
{{ form_label(form.bano) }}
{{ form_widget(form.bano) }} <br>
{% for sub in form.sub %}
{{ form_label(sub.qty) }}
{{ form_widget(sub.qty) }} <br>
{{ form_label(sub.location) }}
{{ form_widget(sub.location) }} <br>
{{ form_label(sub.priority) }}
{{ form_widget(sub.priority) }}<br>
{% endfor %}
{{ form_widget(form.submit) }}
{{ form_end(form) }}

After looking at your code, I think it is possible to make it work, there are a few things you will need to fix. I will edit this answer in a few steps.. Also make a backup/commit of your code before you start changing it.
1) In your MAIN entity (add cascade persist)
/**
* #var Sub
* #ORM\OneToMany(targetEntity="Sub", mappedBy="main", cascade={"persist"})
*/
protected $sub;
2) SUB entity:
Remove protected $mainId; and it's annotation.
Remove cascade={"persist"} from ManyToOne
3) Look at your controller action.
$sub = new Sub();
$sub->setMain($main);
$main->getSub()->add($sub);
Pay attention to the setMain() method. You do not want to do this in controller, but automatically in entity. And also you should add to collection manually, but make a method for it. So you will only have this:
$sub = new Sub();
$main->addSub($sub);
4) In MAIN entity add (you might need to import Sub):
public function addSub(Sub $sub) {
$sub->setMain($this);
$this->sub->add($sub);
return $this;
}
You should also add other methods like removeSub(), removeSub(), getSub(). getSub() returns collection, while the first two will return $this.
5) Controller
Do not persist Sub, but Main. (Doctrine will cascade persistance to Sub)
$em->persist($main);
6) You will need to add 'by_reference' option to sub collection inside you Main Form Type.
->add('sub', 'collection', array('type' => new SubType(), 'by_reference' => false));
This will call the actual addSub() method and not call the add method directly.
7) I do not know why you make a new Main entity below.
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ItemBundle:Main')
->findOneByPono($pono);
$cano = $entity->getCano();
$bano = $entity->getBano();
$main = new Main();
$main->setPono($pono);
$main->setCano($cano);
$main->setBano($bano);
Try to change to:
$em = $this->getDoctrine()->getManager();
$main = $em->getRepository('ItemBundle:Main')
->findOneByPono($pono);
You probably should define Pono as unique.

Related

Correct way to implement a search function in a symfony project?

Im learning Symfony and I'm creating a CRUD app for practicing.
I want to implement a search function in the page where I list my db items. I was wondering what is the correct way to achieve this.
Right now, I have created a searchType and searchController with the next code:
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class searchController extends Controller
{
public function searchAction(){
$formulario = $this->createForm('AppBundle\Form\SearchType');
return $this->render('searchBar.html.twig', ['form' => $formulario->createView()]);
}
}
class SearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('key', ChoiceType::class,
['choices' => [
'Elegir Campo...' => 0,
'Modelo' => 1,
'Marca' => 2,
'Año' => 3,
'Propietario' => 4
]
])
->add('term', TextType::class)
->add('buscar', SubmitType::class)
;
}
}
I have another controller called itemController, where i have the list, add, modify and delete actions. With the twig render() function, I'm rendering the searchBar in the items list page. Which is the correct way to get the values from the 'key' and the 'term' elements and use them to make queries against the db?
I have tried to achieve this without the searchController/searchType and I used a simple <form> in the template and got the key and term values with $request->get() method in the listAction. After I created a switch-case statement to execute queries according to the key value. I could achieve what i wanted like this, but I want to be able to do this the correct way.
Can someone help me/give me some hints on how to continue from this?
Thanks.
Update:
Items Controller:
/**
*#Route("/items", name="items")
*/
public function listAction(Request $request){
$em = $this->getDoctrine()->getManager();
$items = $em->getRepository('AppBundle:Item')->findAll();
return $this->render('items.html.twig', ['items' => $items]);
}
My items.html.twig:
{% extends base.html.twig %}
{% block body %}
{{ render(controller('AppBundle:search:search')) }}
...
{% endblock %}
My searchBar.html.twig:
{{ form_start(form, {'attr': {'class': 'form-inline float-left my-2 my-lg-0'}}) }}
{{ form_widget(form.key) }}
{{ form_widget(form.term, {'attr': {'class': 'ml-1'}}) }}
{{ form_widget(form.buscar, {'attr': {'class': 'btn btn-outline-success ml-1'}}) }}
{{ form_end(form) }}
What i tried with routing and works with the searchController:
/**
* #Route("/search", name="search")
*/
public function searchAction(Request $request){
$em = $this->getDoctrine()->getManager();
$formulario = $this->createForm('AppBundle\Form\SearchType');
$formulario->handleRequest($request);
if($formulario->isSubmitted() && $formulario->isValid()){
$data = $formulario->getData();
$key = $data["key"];
$term = $data["term"];
$items = $em->getRepository('Item::class')->findByTerm($key, $term);
return $this->render('items.html.twig', ['items' => $items]);
}
return $this->render('searchBar.html.twig', ['form' => $formulario->createView()]);
}
If i go to /search and search for an item, it redirects me to my items page with the item i searched. But, If i use the search bar in my items page that i rendered using {{ render(controller('AppBundle:search:search')) }}, it doesn't work.
You are not very far from reaching your goal.
On your Controller, you can update your code to process the incoming request:
public function searchAction(Request $request){
$formulario = $this->createForm('AppBundle\Form\SearchType');
$formulario->handleRequest($request);
if ($formulario->isSubmitted() && $formulario->isValid()) {
$data = $formulario->getData();
// ... perform some action, such as saving the data to the database or search
}
return $this->render('searchBar.html.twig', ['form' => $formulario->createView()]);
}
You can find here more information about Processing Forms
To search into your database, you can process your repositories corresponding to the data. For more information about that, you can go here on Symfony Doctrine documentation
To go further, there is a bundle allowing simplified management of search forms: Lexik Form Filter Bundle

Symfony - how to get data from select html tag in view

I am learning Symfony so I am testing various ways to work with database. The idea is to make select dropdown list that contains data from table in database. Each option in select returns value that is id of column from table. Dropdown list is defined in View in this way ('find_res' in action is route to controller):
<form action="{{ path('find_res') }}" method="POST" name="formpt">
<select name="patientId">
{% for patient in patients %}
{{dump(patient)}}
<option value="{{patient.id}}">{{patient.lastname}}{{patient.firstname}}</option><br />
{% endfor %}
</select>
<button type="submit" name="submit">Find results</button>
</form>
so that for chosen patient.id it should show results in table which is defined in code bellow this as standard html table.
In controller method I created list of all patients from table in database and sent it as parameter to this view. And that works just fine. Also, I would not get into details how query is built because the problem is that any $request I try does not return anything, just null. I tried:
$request->request->get('patientId'); //returns null always
$request->get('patientId'); //also null
I even tried to give name to form in view like for instance 'formpt' and then tried it with:
$request->request->get('formpt')['patientId'];
still nothing. This test code:
if($request->getMethod() == 'POST' ) {
\Doctrine\Common\Util\Debug::dump($request->request->get('patientId'));
exit;
}
always returns NULL or string(0) "" for whatever I put in "dump".
What I am doing wrong?
Thanks!
The following is a simple way to implement what you're trying to do with the standard form component (note that I explicitly didn't create a dedicated form type!).
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints\NotBlank;
use AppBundle\Entity\Patient;
class DefaultController extends Controller
{
/**
* #Route("/", name="index")
*
* #param Request $request
*
* #return Response
*/
public function indexAction(Request $request)
{
$form = $this->createFormBuilder()
->add('patient', EntityType::class, [
'required' => false,
'placeholder' => '--- Select ---',
'class' => Patient::class,
'choice_label' => function (Patient $patient) {
return sprintf(
'%s, %s',
$patient->getLastname(),
$patient->getFirstname()
);
},
'constraints' => [
new NotBlank()
],
])
->getForm()
->handleRequest($request)
;
if ($form->isSubmitted() && $form->isValid()) {
/** #var $selected Patient */
$selected = $form->get('patient')->getData();
dump($selected);
}
return $this->render('default/index.html.twig', [
'form' => $form->createView()
]);
}
}
the view being:
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}
<button>Find results</button>
{{ form_end(form) }}
{% endblock %}
I understand that the form component (especially form customization) has it's learning curve, but ultimately, if you want to use symfony fully you'll end up using it anyway (why reinvent the wheel). So the sooner you start with it the better.
Maybe try this
For mapped field
public function yourAction(Request $request){
$patient = new Patient();
$form = $this->createForm('AppBundle\Form\PatientType', $patient);
$form->handleRequest($request);
if ($form->isSubmitted())
{
$patientId = $patient->getId();
}
}
If you need to get a non mapped field (field that's not a Patient property)
public function yourAction(Request $request){
$patient = new Patient();
$form = $this->createForm('AppBundle\Form\PatientType', $patient);
$form->handleRequest($request);
if ($form->isSubmitted())
{
$patientCustomField = $form['customField']->getData();
}
}

Build Form with Single Table Inheritance

I have my entity Article and one single table inheritance like this :
/**
* Article
*
* #ORM\Table(name="article")
* #ORM\Entity(repositoryClass="PM\PlatformBundle\Repository\ArticleRepository")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="media", type="string")
* #ORM\DiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image", "text" = "Text"})
*/
class Article
{
protected $id;
protected $title;
protected $description;
protected $author;
//other attributes and setters getters
}
class Image extends Article
{
private $path;
//getter setter
}
class Movie extends Article
{
private $url;
//getter setter
}
So my article's object type is either Image or movie or text only. Ok now I would like build a form wherein users can post a new article : in this form, the user has to choice between tree type (3 radios button) : image OR movie OR text only and of course the other fields : title and description. How I can do that ? Because with the command
php bin/console doctrine:generate:form myBundle:Article
The form rendered is :
class ArticleType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class)
->add('description', TextareaType::class)
->add('save', SubmitType::class);
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PM\PlatformBundle\Entity\Article'
));
}
}
I don't know the way to implement my STI relation in this form. Because I have not field in my Article entity/object for the type (only in my table).
I have to add a Custom ChoiceType() field but it require a attribute.
When I try to add this in the form :
->add('path', SearchType::class)
->add('url', UrlType::class)
I got this error :
Neither the property "path" nor one of the methods "getPath()", "path()", "isPath()", "hasPath()", "__get()" exist and have public access in class "PM\PlatformBundle\Entity\Article".
Because I have create an instance of Article, not an instance of Image or Movie. Initially I created a STI thinking a new instance of Article would allow me also to define the "type" of article. But not ? Right ?
You will have to make three forms (one for an Article, one for a Movie and one for an Image). Then, in your controller, you have to options to deal with them:
Either you use one action to handle the three forms (you can check wich one is submitted by using $form->isSubmitted())
You create one action by form, and set the form action URL for each form to the correct controller.
Finally, in your template, you encapsulate your forms in a div, and use the example in my previous post.
{% extends "CoreBundle::layout.html.twig" %}
{% block title %}{{ parent() }}{% endblock %}
{% block btn_scrollspy %}
{% endblock %}
{% block bundle_body %}
<div class="well">
<div class="selector">
<input type="radio" name="form-selector" value="article-form"> Article
<input type="radio" name="form-selector" value="movie-form"> Movie
<input type="radio" name="form-selector" value="image-form"> Image
</div>
<div class="form article-form" style="display: none;">
{{ form(articleForm) }}
</div>
<div class="form movie-form" style="display: none;">
{{ form(movieForm) }}
</div>
<div class="form image-form" style="display: none;">
{{ form(imageForm) }}
</div>
</div>
{% endblock %}
I agree with dragoste in the comments: you can't expect the form to deduce by himself the type of class you want to instantiate based on a value.
Roughly, Image and Movie are the same type as Article, but an Article is not an Image and/or a Movie.
You will have to check that manually. You can do that server side like explained in the comments, with a field using mapped: false to determine the type of entity you need to instantiate, or client side with javascript by using three forms (one for a movie, one for an article, one for an image) and by displaying the correct one based on your radio button.
Edit: How to display the correct form in JS?
I created a JSFiddle to show you how you can do this using jQuery : https://jsfiddle.net/61gc6v16/
With jQuery documentation, you should be able to quickly understand what this sample do, and to adapt it to your needs. :)
#Boulzy I did this and it works:
class ArticleController extends Controller
{
public function addAction(Request $request)
{
$form1 = $this->get('form.factory')->create(TextOnlyType::class);
$form2 = $this->get('form.factory')->create(ImageType::class);
$form3 = $this->get('form.factory')->create(MovieType::class);
return $this->render('PMPlatformBundle:Article:add.html.twig', array(
'ArticleTextform' => $form1->createView(),
'ArticleImageform' => $form2->createView(),
'ArticleMovieform' => $form3->createView(),
));
}
public function addArticleTextAction(Request $request)
{
$ArticleText = new TextOnly;
$form = $this->get('form.factory')->create(TextOnlyType::class, $ArticleText);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
$ArticleText->setAuthor(5);
$ArticleText->setLikes(0);
$em = $this->getDoctrine()->getManager();
$em->persist($ArticleText);
$em->flush();
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
$listComments = $ArticleText->getComments();
return $this->render('PMPlatformBundle:Article:view.html.twig', array(
'article' => $ArticleText,
'listComments' => $listComments
));
}
return $this->render('PMPlatformBundle:Article:add.html.twig', array(
'form' => $form->createView(),
));
}
public function addArticleImageAction(Request $request)
{
//the same system as TextOnly
}
public function addArticleMovieAction(Request $request)
{
//the same system as TextOnly
}
}
(I override action directly in my template. With POST method.)
addAction is my contoller which is called by route for display the view of three forms. As you can see this code works as long as there is no error on submitted form. Because, in this case (when error occured when a form is submitted) each controller needs to return the initial view with the 3 forms. How I can do that ?

Add dropdown to symfony 3 form

I want to add a dropdow field for category in my form in symfony version 3, I have tried to solutions but each one have their own problem
First got all categories and pass them to my view and show them:
Action:
/**
* Creates a new News entity.
*
* #Route("/new", name="news_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$news = new News();
$form = $this->createForm('AppBundle\Form\NewsType', $news);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($news);
$em->flush();
return $this->redirectToRoute('news_show', array('id' => $news->getId()));
}
$em = $this->getDoctrine()->getManager();
$categories = $em->getRepository('AppBundle:Category')->findAll();
return $this->render('news/new.html.twig', array(
'news' => $news,
'form' => $form->createView(),
'categories' => $categories,
));
}
View:
{% extends 'base.html.twig' %}
{% block body %}
<h1>News creation</h1>
{{ form_start(form) }}
<label for="news_content" class="required">Category</label>
<select name="news[categoryId]">
{% for category in categories %}
<option value="{{ category.id }}">{{ category.title }}</option>
{% endfor %}
</select>
{{ form_widget(form) }}
<input class="btn btn-sm btn-success" type="submit" value="Create" />
{{ form_end(form) }}
<ul>
<li>
<a class="label label-sm label-info" href="{{ path('news_index') }}">Back to the list</a>
</li>
</ul>
{% endblock %}
The form is created as I expected but when i want to submit it, it show an validation error as bellow:
This form should not contain extra fields.
second solution that I have tried is to generate the dropdown from my Type, so in NewsType I changed the buildForm function as bellow:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('categoryId', EntityType::class, [
'class' => 'AppBundle:Category',
'choice_label' => 'title',
])
->add('title')
->add('content')
;
}
It this way, the form also have been created nicely but after submit, an database exception returned and said:
An exception occurred while executing 'INSERT INTO news (category_id, title, content) VALUES (?, ?, ?)' with params [{}, "asdf", "asdf"]:
Catchable Fatal Error: Object of class AppBundle\Entity\Category could not be converted to string
It mean that my category_id passed as an object !
What should I do?
BTW, my english is a little weak, please do not put and minus on my post, I had been ban multiple times.
Thanks in advance.
all symfony is trying to do is to find a string representation of the Category object, so it can populate the option fields.
you can solve this in a couple of ways:
In the Category object, you can make a __toString method.
public function __toString() {
return $this->name; // or whatever field you want displayed
}
or
you can tell symfony which field to use as the label for the field. From docs
$builder->add('attending', ChoiceType::class, array(
'choices' => array(
new Status(Status::YES),
new Status(Status::NO),
new Status(Status::MAYBE),
),
'choice_label' => 'displayName', // <-- where this is getDisplayName() on the object.
));

Symfony 2: Multiple forms generated list of objects

I would like to generate page with list of users names and next to every user I would like to have button which would activate/deactivate this user.
I could of course create link with user ID and GET method in controller which would perform operation when link would be clicked. As far as I know it is not recommended though to do it this way due to security concerns. So instead of links to route which would perform operation I would like to have forms and buttons to submit request to PUT route which would change user status.
QUESTION: how to generate such forms (buttons) based on list of users returned by Doctrine?
Form code used to create form/button in user profile:
/**
* Creates a form to activate/deactivate a User entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createActivationDeactivationForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('user_activate', array('id' => $id)))
->setMethod('PUT')
->add('submit', 'submit', array('label' => 'Activate/Deactivate'))
->getForm()
;
}
Controller code used for user profile:
/**
* #Route("/user/{id}", name="user_show")
* #Method("GET")
* #Template()
*/
public function showUserAction($id)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$deleteForm = $this->createDeleteForm($id);
$activateForm = $this->createActivationDeactivationForm($id);
return array(
'user' => $user,
'delete_form' => $deleteForm->createView(),
'activate_form' => $activateForm->createView(),
);
}
Controller PUT method to perform operation from user profile:
/**
* Activate a user.
*
* #Route("/{id}", name="user_activate")
* #Method("PUT")
*/
public function activateAction(Request $request, $id)
{
$form = $this->createActivationDeactivationForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$current_user_activity_flag = $user->getActive();
$user->setActive(abs($current_user_activity_flag-1));
$em->persist($user);
$em->flush();
}
return $this->redirect($this->getRequest()->headers->get('referer'));
}
Controller code to be used for users list:
/**
* #Route("/users", name="users_list")
* #Method("GET")
* #Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('TestUserBundle:User')->findExistingUsers();
//$deleteForm = $this->createDeleteForm($id);
//$activateForm = $this->createActivationDeactivationForm($id);
return array(
'users' => $users,
//'delete_form' => $deleteForm->createView(),
//'activate_form' => $activateForm->createView(),
);
}
I can not pass ID to form like I did for operation from profile cause for every user there is different ID and more of that Symfony generates only first form and ignores rest.
Any idea how to handle it? Or maybe my approach with form/buttons is incorrect and I should just use links instead?
I found solution which works though I am not sure about if it's compliant with best practices.
Instead of passing one form object in controller I generated an array of them with keys based on user ID. Than when looping through array in TWIG template I use user ID to refer form object created for current user.
Mentioned in question controller for user listing should than look like this:
/**
* #Route("/users", name="users_list")
* #Method("GET")
* #Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('PSUserBundle:User')->findExistingUsers();
$activate_forms = array();
$delete_forms = array();
foreach($users as $user)
{
$activate_forms[$user->getId()] = $this->createActivationDeactivationForm($user->getId())->createView();
$delete_forms[$user->getId()] = $this->createDeleteForm($user->getId())->createView();
}
return array(
'users' => $users,
'delete_forms' => $delete_forms,
'activate_forms' => $activate_forms,
);
}
... and in TWIG form within foreach should be refered like this:
{{ form_start(activate_forms[user.id], {'attr': {'novalidate': 'novalidate'}}) }}
{% if user.active %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-warning btn-block'}, 'label' : 'Deactivate'}) }}
{% else %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-success btn-block'}, 'label' : 'Activate'}) }}
{% endif %}
{{ form_end(activate_forms[user.id]) }}

Categories