Pour réaliser l'exemple vous devez disposer:
D'un projet symfony2 déjà en place
une base de donnée
J'ai utilisé le bundle AcmeDemoBundle automatiquement installé avec la commande
symfony new
Bundle existant
Pour info il existe deux supers bundles existant qui marchent très bien
https://github.com/stwe/DatatablesBundle
https://github.com/AliHichem/AliDatatableBundle
Dans notre exemple on va rester simple et le plus découplé possible coté vue qui sera facilement changeable par une autre purement html totalement isolé du site symfony2 (ce dernier jouera seulement le rôle de fournisseur d'api)
Présentation du plugin dataTable
Le plugin datatable offre une manière élégante pour transformer des tableaux purement html en un tableau riche en fonctionnalités (Pagination, tri, filtrage, ...) avec un minimum de code JavaScript.
Je ne vais trop rentrer en détail car la doc officiel du script est largement complète.
Lien vers la doc.
Problématique:
par contre en travaillant avec cette librairie vous remarquerez que si le nombre de données à gérer augmente, la page rame et les interactions perdent leurs fluidités.
Solutions:
Récupérer en ajax les données du tableau
Pour cela voici le code source de l'exemple (j'ai essayé de rester le plus simple possible) qui couvre cette fonctionnalité de datatable (Server side processing)
@le Modele
Code php : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?php namespace Acme\DemoBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * User * * @ORM\Entity(repositoryClass="Acme\DemoBundle\Repository\UserRepository") * @ORM\Table(name="users") */ class User { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var string * * @ORM\Column(type="string") */ private $name; /** * @var string * * @ORM\Column(type="datetime") */ private $createdAt; public function __construct() { $this->createdAt = new \dateTime('now'); } public function getId() { return $this->id; } public function getName() { return $this->name; } public function getCreatedAt() { return $this->createdAt; } } |
Code twig : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | {% extends "AcmeDemoBundle::layout.html.twig" %} {% block head %} {{ parent() }} <link rel="stylesheet" href="https://cdn.datatables.net/1.10.6/css/jquery.dataTables.min.css" /> <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script> <script src="https://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script> <script> $(function() { $('#user-list').DataTable({ "processing": true, "serverSide": true, "ajax": "{{ path('user_paginate') }}", "sAjaxDataProp": "data", "pageLength": 10, "columns":[ {"data": "id"}, {"data": "name"}, {"data": "created_at"} ] }); }); </script> {% endblock %} {% block body %} <table id="user-list"> <thead> <tr> <th>ID</th> <th>Nom</th> <th>Crée le</th> </tr> </thead> <tbody> </tbody> </table> {% endblock %} |
@Le Controlleur
Code php : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class UserController extends Controller { /** * @Route("/list", name="user_list") */ public function indexAction() { return $this->render('AcmeDemoBundle:User:index.html.twig',array()); } /** * @Route("/paginate", name="user_paginate") */ public function paginateAction(Request $request) { $length = $request->get('length'); $length = $length && ($length!=-1)?$length:0; $start = $request->get('start'); $start = $length?($start && ($start!=-1)?$start:0)/$length:0; $search = $request->get('search'); $filters = [ 'query' => @$search['value'] ]; $users = $this->getDoctrine()->getRepository('AcmeDemoBundle:User')->search( $filters, $start, $length ); $output = array( 'data' => array(), 'recordsFiltered' => count($this->getDoctrine()->getRepository('AcmeDemoBundle:User')->search($filters, 0, false)), 'recordsTotal' => count($this->getDoctrine()->getRepository('AcmeDemoBundle:User')->search(array(), 0, false)) ); foreach ($users as $user) { $output['data'][] = [ 'id' => $user->getId(), 'name' => $user->getName(), 'created_at' => $user->getCreatedAt()->format('Y-m-d'), ]; } return new Response(json_encode($output), 200, ['Content-Type' => 'application/json']); } } |
Code php : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?php namespace Acme\DemoBundle\Repository; use Doctrine\ORM\EntityRepository; class UserRepository extends EntityRepository { public function search($data, $page = 0, $max = NULL, $getResult = true) { $qb = $this->_em->createQueryBuilder(); $query = isset($data['query']) && $data['query']?$data['query']:null; $qb ->select('u') ->from('AcmeDemoBundle:User', 'u') ; if ($query) { $qb ->andWhere('u.name like :query') ->setParameter('query', "%".$query."%") ; } if ($max) { $preparedQuery = $qb->getQuery() ->setMaxResults($max) ->setFirstResult($page * $max) ; } else { $preparedQuery = $qb->getQuery(); } return $getResult?$preparedQuery->getResult():$preparedQuery; } } |
- Améliorer la récupération des résultats (getSingleScalarResult au lieux du count)
- Alléger le contrôleur
- Ajouter le tri des résultats
- Formater les cellules d'une façon particulière
- Ajouter les actions
- Ajouter des actions groupées (bash actions)
@Todo
Test !!
@Code source sur github
très bientôt disponible