Git Product home page Git Product logo

ideupsimplepaginatorbundle's Introduction

SimplePaginator bundle for Symfony2/Doctrine2/Twig

This package contains a bundle to easily paginate complex queries efficiently and without effort.

How to include SimplePaginatorBundle in your code

You should clone this repository in your Symfony's vendor/bundles directory, add it into autoload.php file:

<?php
$loader->registerNamespaces(array(
  'Symfony' => array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'),
  ...
  'Ideup'   => __DIR__.'/../vendor/bundles',
  );

... and in your AppKernel.php file:

<?php
public function registerBundles()
{
    $bundles = array(
      ...
        new Ideup\SimplePaginatorBundle\IdeupSimplePaginatorBundle(),
      );
}

... so you are ready now to use IdeupSimplePaginatorBundle as a service.

Since the Paginator::paginate() method needs a Query object to work with, you need to change slightly your entity Repository classes:

  • Before
<?php
class User extends EntityRepository 
{
  public function findByMyCriteria() {
    $query = $this->_em->createQuery('...');
    return $query->getResult();
  }
}
  • After
<?php
class User extends EntityRepository 
{
  public function findByMyCriteria() {
    return $this->findByMyCriteriaDQL()->getResult();
  }

  public function findByMyCriteriaDQL() {
    $query = $this->_em->createQuery('...');
    return $query;
  }
}

In your controller you can be able to instantiate the paginator service. SimplePaginatorBundle is smart enough to detect the current page and the maximum items per page from the Request context, so you don't need to type more boilerplate code!

  • Before
<?php
class MyController extends Controller
{
  public function listAction() {
    $paginator = $this->get('ideup.simple_paginator');

    $users = $paginator->paginate($em->getRepository('MyBundle:User')->findByMyCriteriaDQL())->getResult();

    $vars = array(
        'users'     => $users,
        'paginator' => $paginator);
    return $this->render('MyBundle:User:list.html.twig', $vars);
  }
}

Note that the variable $users contains only the paginated subset of the Doctrine collection and you can query $paginator object to obtain information about the pagination process; such as how many items are in the full collection, in wich page are we, wich is the last page, etc.

  • After
<?php
class MyController extends Controller
{
  public function listAction() {
    $paginator = $this->get('ideup.simple_paginator');

    $users = $paginator->paginate($em->getRepository('MyBundle:User')->findByMyCriteriaDQL())->getResult();

    $vars = array(
        'users'     => $users,
    );
    return $this->render('MyBundle:User:list.html.twig', $vars);
  }
}

Note that now you don't need to pass $paginator variable to template unless you want to obtain information about pagination process.

How to render a paginator in your view

  • Before
<ul id="paginate_elements">
  {% if paginator.currentPage > 1 %}
    <li><a href="{{ path('my_controller_route', {'page': paginator.previousPage}) }}">previous</a></li>
  {% else %}
    <li class="left_disabled"><a href="#">previous</a></li>
  {% endif %}

  {% for page in paginator.minPageInRange..paginator.maxPageInRange %}
    {% if page == paginator.currentPage %}
      <li><a class="current" href="#">{{ page }}</a></li>
    {% else %}
      <li><a href="{{ path('my_controller_route', {'page': page}) }}">{{ page }}</a></li>
    {% endif %}
  {% endfor %}

  {% if paginator.currentPage < paginator.lastPage %}
    <li class="right"><a href="{{ path('my_controller_route', {'page': paginator.nextPage}) }}">next</a></li>
  {% else %}
    <li class="right_disabled">next</li>
  {% endif %}
</ul>
  • After
  {{ simple_paginator_render('my_controller_route') }}

You can to customize paginator view as follows:

  {{ simple_paginator_render('my_controller_route', null, { params }) }}

where params may be:

  • 'container_class' Default simple_paginator

  • 'previosPageText' Default previous

  • 'previousEnabledClass' Default left,

  • 'previousDisabledClass' Default left_disabled,

  • 'firstPageText' Default first,

  • 'firstEnabledClass' Default first,

  • 'firstDisabledClass' Default first_disabled,

  • 'lastPageText' Default last,

  • 'lastEnabledClass' Default last,

  • 'lastDisabledClass' Default last_disabled,

  • 'nextPageText' Default next,

  • 'nextEnabledClass' Default `right',

  • 'nextDisabledClass' Default right_disabled,

  • 'routeParams' Default {}

For example, if you want to customize paginator view to show a route that receive a parameter id and you want to change container class:

  {{ simple_paginator_render('my_controller_route', null, { 
       'routeParams' : {'id' : id},
       'container_class' : 'custom_simple_paginator_class'
     })
  }}

If your needs are out of this sight you can customize it in your own view:

  {{ simple_paginator_render('my_controller_route', null, {....}, 'MyBundle:MyViewFolder:MyViewFile.html.twig') }}

To create MyBundle:MyViewFolder:MyViewFile.html.twig copy from default template that is included inside the bundle Resources\views\Paginator\simple-paginator-list-view.html.twig and customize it in your own Bundle.

For example, if you want only to show paginator numbers, your template sounds like this

MyBundle\Resources\views\MyViewFolder\MyViewFile.html.twig:

<ul class="{{ container_class }}">
    <!-- NUMBERS -->
    {% for page in minPage..maxPage %}
        {% if page == currentPage %}
            <li class="{{ currentClass }}">
                {{ page }}
            </li>
        {% else %}
            {% set rParams =  {'page': page, 'paginatorId': id} | merge(routeParams) %}
            <li>
                <a href="{{ path(route, rParams) }}">{{ page }}</a>
            </li>
        {% endif %}
    {% endfor %}
</ul>

How to include more than one paginator in a single view

SimplePaginatorBundle supports multiple paginators, you should specify an id in your controller and view calls. Note that you can modify the particular properties of each paginator.

  • Before
<?php
class MyController extends Controller
{
  public function listAction() {
    $paginator = $this->get('ideup.simple_paginator');

    $paginator->setItemsPerPage(25, 'users');
    $users = $paginator->paginate($em->getRepository('MyBundle:User')->findByMyCriteriaDQL(), 'users')->getResult();

    $paginator->setItemsPerPage(5, 'groups');
    $groups = $paginator->paginate($em->getRepository('MyBundle:User')->findByMyCriteriaDQL(), 'groups')->getResult();

    $vars = array(
        'users'     => $users,
        'groups'    => $groups,
        'paginator' => $paginator);
    return $this->render('MyBundle:User:list.html.twig', $vars);
  }
}

In the view you also need to specify the paginator id:

<ul id="paginate_elements">
  {% if paginator.currentPage('users') > 1 %}
    <li><a href="{{ path('my_controller_route', {'page': paginator.previousPage('users'), 'paginatorId': 'users'}) }}">previous</a></li>
  {% else %}
    <li class="left_disabled"><a href="#">previous</a></li>
  {% endif %}

  {% for page in paginator.minPageInRange('users')..paginator.maxPageInRange('users') %}
    {% if page == paginator.currentPage('users') %}
      <li><a class="current" href="#">{{ page }}</a></li>
    {% else %}
      <li><a href="{{ path('my_controller_route', {'page': page, 'paginatorId': 'users'}) }}">{{ page }}</a></li>
    {% endif %}
  {% endfor %}

  {% if paginator.currentPage('users') < paginator.lastPage('users') %}
    <li class="right"><a href="{{ path('my_controller_route', {'page': paginator.nextPage('users'), 'paginatorId': 'users'}) }}">next</a></li>
  {% else %}
    <li class="right_disabled">next</li>
  {% endif %}
</ul>
  • After
<?php
class MyController extends Controller
{
  public function listAction() {
    $paginator = $this->get('ideup.simple_paginator');

    $users = $paginator
      ->setItemsPerPage(25, 'users');
      ->paginate($em->getRepository('MyBundle:User')->findByMyCriteriaDQL(), 'users')
      ->getResult()
    ;

    // Now also we can paginate arrays
    $allGroups = array('group1', 'group2', 'group3', 'group4', 'group5');

    $groups = $paginator
      ->setItemsPerPage(3, 'groups')
      ->paginate($allGroups, 'groups')
      ->getResult()
    ;

    $vars = array(
        'users'     => $users,
        'groups'    => $groups,
    );
    return $this->render('MyBundle:User:list.html.twig', $vars);
  }
}

In the view you also need to specify the paginator id:

  {{ simple_paginator_render('my_controller_route', 'users', {....}) }}
  
  {{ simple_paginator_render('my_controller_route', 'groups', {....}) }}

Authors

  • Francisco Javier Aceituno
  • Luis Cordoval
  • Moisés Maciá
  • Gustavo Piltcher

Changelog

v0.91

  • Added support to paginate arrays.

  • Changed setter methods. Now this methods return paginate object.

  • Added twig support.

v0.9

  • Added dependency to DoctrineExtensions\Paginate to handle proper pagination (see https://github.com/beberlei/DoctrineExtensions)

  • Added support to paginate multiple lists at once

  • Changed the Paginador class name to Paginator, this is how services.xml defines our service, with a parameter set to the class implementing pagination and passing a service id

<parameters>
  <parameter key="simple_paginador.class">Ideup\SimplePaginatorBundle\Paginator\Paginator</parameter>
</parameters>

<services>
  <service id="ideup.simple_paginator" class="%simple_paginator.class%">
    <argument type="service" id="request" strict="false" />
  </service>
</services>

TODO

  • Support more types
  • Testing it with a hello world sample
  • Making it work with a more generic Doctrine Collections

ideupsimplepaginatorbundle's People

Contributors

cordoval avatar gustavopiltcher avatar javiacei avatar mmacia avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.