Reputation: 11
Let's imagine that we want to assign categories to a post, we use an EntityType to generate them based on the amount of categories we have, so we just add the next block of code to our form:
Controller:
->add('categories', EntityType::class, array(
'class' => Category::class,
'choice_label' => 'category_description',
'multiple' => true,
'expanded' => true,
'required' => false,
))
And then save them to the database when the form is submitted, ManyToMany, using ArrayCollection:
foreach($post_data['categories'] as $form_category)
{
$database_category = $database_manager->getRepository(Category::class)->find($form_category->getId());
$post->addCategory($database_category);
}
Entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="App\Repository\PostRepository")
*/
class Post
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
...
/**
* @ORM\ManyToMany(targetEntity="Category", cascade={"persist"})
* @ORM\JoinTable(name="junction_table",
* joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")}
* )
*/
private $categories;
public function __construct() {
$this->categories = new ArrayCollection();
}
...
public function getCategories()
{
return $this->categories;
}
public function addCategory(Category $category): self
{
$this->categories->add($category);
return $this;
}
}
Image:
Generated checkboxes with description and index
But what if i want to have those checkboxes preselected when i go to edit mode so the user knows which ones were selected last time, how would you approach that?
Also how would you remove one if it is deselected?
Upvotes: 0
Views: 704
Reputation: 636
If your form fields are mapped to an entity, the data should be set automatically. You don't even have to add the categories manually to the post.
Here is a full sample of working code that matches what you want to do:
//src/Entity/Group.php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
* @ORM\Table(name="`group`")
*/
class Group
{
/**
* Group constructor.
*/
public function __construct()
{
$this->players = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Player", inversedBy="groups")
*/
private $players;
/**
* @return mixed
*/
public function getPlayers()
{
return $this->players;
}
/**
* @param mixed $players
*
* @return Group
*/
public function setPlayers($players)
{
$this->players = $players;
return $this;
}
/**
* @param Player $player
*
* @return Group
*/
public function addPlayer(Player $player)
{
$this->players->add($player);
return $this;
}
/**
* @param Player $player
*
* @return Group
*/
public function removePlayer(Player $player)
{
$this->players->removeElement($player);
return $this;
}
}
//src/Entity/Player.php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\PlayerRepository")
*/
class Player
{
/**
* @return string
*/
public function __toString()
{
return $this->name;
}
/**
* Player constructor.
*/
public function __construct()
{
$this->groups = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Group", mappedBy="players")
*/
private $groups;
/**
* @return mixed
*/
public function getGroups()
{
return $this->groups;
}
/**
* @param mixed $groups
*
* @return Player
*/
public function setGroups($groups)
{
$this->groups = $groups;
return $this;
}
/**
* @param Group $group
*
* @return Player
*/
public function addGroup(Group $group)
{
$this->groups->add($group);
return $this;
}
/**
* @param Group $group
*
* @return Player
*/
public function removeGroup(Group $group)
{
$this->groups->removeElement($group);
return $this;
}
}
//src/Form/GroupType.php
namespace App\Form;
use App\Entity\Group;
use App\Entity\Player;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GroupType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'players',
EntityType::class,
[
'class' => Player::class,
'multiple' => true,
'expanded' => true,
'required' => false,
]
);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => Group::class,
]
);
}
}
//src/Controller/GroupController.php
namespace App\Controller;
use App\Entity\Group;
use App\Form\GroupType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class GroupController extends Controller
{
/**
* @Route("/edit-group/{id}", name="group_edit")
* @param Request $request
* @param Group $group
*
* @return Response
*/
public function editGroup(Request $request, Group $group)
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(GroupType::class, $group);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($group);
$em->flush();
}
return new Response(
$this->renderView(
'group/edit-group.html.twig',
array(
'form' => $form->createView(),
)
)
);
}
}
//templates/group/edit-group.html.twig
{% extends 'base.html.twig' %}
{% block body %}
<div class="container">
<div class="row">
<h1>Edit group</h1>
</div>
{{ form_start(form) }}
{{ form_row(form.players) }}
<button type="submit" class="btn btn-success">Edit</button>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
{% endblock %}
Upvotes: 1