Tuto #2 : DoctrineExtension Tree, représentation d’un arbre dans un champ select

Dans ce tuto nous allons afficher la représentation d’un arbre tree dans un champ select.

Bundle concernés :

Pré-requis :

Table des matières :

  • Step 1 : Créer le repository de notre futur entité
  • Step 2 : Créer et configurer notre entité
  • Step 3 : Créer et configurer notre form type
  • Step 4 : Enregistrer notre form type comme service
  • Step 5 : Utiliser notre représentation d’arbre tree dans un champ select

Step 1 : Créer le repository de notre futur entité

Dans un premier temps, nous allons devoir créer le repository de notre futur entité. Ce repository sera utilisé dans le form type de notre entity. On comnence par créer le repository car notre entité est dépendante de ce dernier. Voici la class du répository :


namespace AppBundle\Repository;

// Cette clas fournit un certains nombre de fonction qui vous facilite la vie
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;

/**
 * Description of CategoryRepository
 * 
 * @author Hubsine
 */
class CategoryRepository extends NestedTreeRepository{
   
}

Step 2 : Créer et configurer notre entité

Dans un second temps nous allons créer notre entité qui va représenter notre arbre tree. Ici il s'agit d'un arbre de catégorie.



namespace AppBundle\Entity;

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;

/**
 * Description of Category
 *
 * @Gedmo\Tree(type="nested")
 * @ORM\Table(name="categories")
 *
 * Le repository créer plus haut
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
 * 
 * @author Hubsine
 */
class Category {
    
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @ORM\Column(length=64)
     */
    private $title;

    /**
     * @Gedmo\TreeLeft
     * @ORM\Column(type="integer")
     */
    private $lft;

    /**
     * @Gedmo\TreeLevel
     * @ORM\Column(type="integer")
     */
    private $lvl;

    /**
     * @Gedmo\TreeRight
     * @ORM\Column(type="integer")
     */
    private $rgt;

    /**
     * @Gedmo\TreeRoot
     * @ORM\ManyToOne(targetEntity="Category")
     * @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
     */
    private $root;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
     * @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
     */
    private $parent;

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
     * @ORM\OrderBy({"lft" = "ASC"})
     */
    private $children;

    public function getId()
    {
        return $this->id;
    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function getRoot()
    {
        return $this->root;
    }

    public function setParent(Category $parent = null)
    {
        $this->parent = $parent;
    }

    public function getParent()
    {
        return $this->parent;
    }
     
    public function getLvl(){
        
        return $this->lvl;
    }
    
}

Step 3 : Créer et configurer notre form type

Dans le step 3 nous allons créer notre formulaire qui permet d'afficher notre arbre dans un champ select. C'est là que va se jouer l'affichage de l'arbre.


namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\Category;

class CategoryType extends AbstractType
{
    
    private $em;
    private $repo;
            
    public function __construct(EntityManager $em) {
        
        $this->em = $em;
        $this->repo = $this->em->getRepository('AppBundle:Category');
    }
    
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('parent', EntityType::class, array(
                'label' => 'Catégorie parent',
                    'required'  =>  false,
                    'class' => 'AppBundle:Category',
                    'choice_label'  => function(Category $category){
                        
                        $prefix = str_repeat('-', $category->getLvl());
                        
                        return $prefix . ' ' . $category->getTitle();
                    },
                    'multiple'  => false,
                    'expanded'  => false,
                    'query_builder' => function(EntityRepository $er){
                        
                        return $er
                                ->createQueryBuilder('node')
                                ->orderBy('node.root, node.lft', 'ASC');
                    }
            ));
    }
    
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Category'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_category';
    }


}

Step 4 : Enregistrer notre form type comme service

Il faut maintenant déclarer notre formulaire type comme service.


parameters:
    app_budle.category.form.type.class: AppBundle\Form\Type\CategoryType
    
services:
    app_bundle.form.type.about_users:
        class: '%app_budle.category.form.type.class%'
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: form.type } 

Step 5 : Utiliser notre représentation d'arbre dans un select

Nous voilà à l'étape finale de notre tuto. Il s'agit d'afficher notre formulaire. On utilisera bien sur un controller pour ce faire.

Controller :


namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\Category;

/**
 * Description of CategoryController
 *
 * @author Hubsine
 */
class CategoryController extends Controller{
    
    /**
     * @Route("/")
     * @Route("/category/new", name="app_bundle_category_new")
     */
    public function newAction(Request $request){
        
        /** @var $categoryFormType \AppBundle\Form\Type\CategoryType */
        $categoryFormType = $this->get('app_bundle.form.type.about_users');
        
        $category = new Category();
        
        $form = $this->createForm($categoryFormType, $category);
        $form->handleRequest($request);
        
        if($form->isSubmitted() && $form->isValid()){
            
            $em = $this->getDoctrine()->getManager();
            $em->persist($category);
            $em->flush();
            
            // Message flash
            $this->addFlash('success', 'La catégorie est ajoutée avec succès.');
            
            // Re-initialise le formulaire pour pouvoir ajouter une nouvelle catégorie
            // Vous pouvez aussi rediriger vers une page
            
            $form = $this->createForm($categoryFormType, new Category());
        }
        
        return $this->render(':Category:new.html.twig', array(
            'form'  => $form->createView()
        ));
    
    }
}

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *