Giter Site home page Giter Site logo

ideupsimplepaginatorbundle's Introduction

SimplePaginator bundle for Symfony2/Doctrine2/Twig

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

Dependencies

For the bundle to work properly you should also install DoctrineExtensions\Paginate.

Bundle and instructions at https://github.com/beberlei/DoctrineExtensions

Installation using composer

Add IdeupSimplePaginatorBundle in your composer.json:

"require": {
        "php": ">=5.3.3",
        "symfony/symfony": "2.1.*",
          .
          .
          .
          .
          .
        "ideup/simple-paginator-bundle":"*"
    }

Now download and install the bundle

$ php composer.phar update ideup/simple-paginator-bundle

Composer will install the bundle to your project's vendor/ideup directory.

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:

  • routeParams, the params needed by the controller route (default: {})

  • container_class, the CSS class applied to the <ul> element that wraps the paginator (default: simple_paginator)

  • firstPageText, the text shown on the first page link (default: first)

  • firstEnabledClass, the CSS class applied to the first page link if there is a first page (default: first)

  • firstDisabledClass, the CSS class applied to the first page text when there is no first page (default: first_disabled)

  • previousPageText, the text shown on the previous page link (default: previous)

  • previousEnabledClass, the CSS class applied to the previous page link if there is a previous page (default: left)

  • previousDisabledClass, the CSS class applied to the previous page text when there is no previous page (default: left_disabled)

  • currentClass, the CSS class applied to the <li> element that wraps the current page link (default: current)

  • nextPageText, the text shown on the next page link (default: next)

  • nextEnabledClass, the CSS class applied to the next page link if there is a next page (default: right)

  • nextDisabledClass, the CSS class applied to the next page text when there is no next page (default: right_disabled)

  • lastPageText, the text shown on the last page link (default: last)

  • lastEnabledClass, the CSS class applied to the last page link if there is a last page (default: last)

  • lastDisabledClass, the CSS class applied to the last page text when there is no last page (default: last_disabled)

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', {....}) }}

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>

ideupsimplepaginatorbundle's People

Contributors

cordoval avatar criscosg avatar egulias avatar gustavopiltcher avatar javiacei avatar javiereguiluz avatar mmacia avatar nass600 avatar phansys avatar sethunath avatar tolbier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ideupsimplepaginatorbundle's Issues

No Tests!

I've realised that there are no Tests folder neither unit tests. They need to be added.

Would also be nice to have Travis CI integration (another issue?).

Regards,

Eduardo.

Error cuando hay mas de 10 items en la base de datos

Seguí las instrucciones y lo hice trabajar pero cuando existen mas de 10 registros en la base de datos explota con este error.
En la documentación no dice nada sobre modificar las rutas, así que no se lo que pasa.

An exception has been thrown during the rendering of a template ("The "libros_show" route has some missing mandatory parameters ("id").") in IdeupSimplePaginatorBundle:Paginator:simple-paginator-list-view.html.twig at line 35.

Google traslated text:
Follow the instructions and I did work but when there are more than 10 records in the database explodes with this error.
The documentation says nothing about changing the routes, so it is not what happens.

The Bundlw doesn't play well with Assetic

Once IdeupPaginatorBundle is active and loaded in AppKernel.php, the command assetic:dump doesn't work at all.
This is the error I got:

[Symfony\Component\DependencyInjection\Exception\InactiveScopeException]
You cannot create a service ("request") of an inactive scope ("request").

The problem seems that resides in the Request dependency. This service is not available in CLI mode. Can we move Request out of constructor?

Update Documentation

Changelog part of README.md reflects a dependency not exposed in the installation part.

queries fail to join

when I do a query with a "join" the result of the pagination does not match the parameter "itemsPerPage", eg:

$this->createQueryBuilder("u")
->select("c, r, u")
->leftJoin("u.cities", "c")
->leftJoin("u.roles", "r")
->orderBy("u.username", "ASC")
->getQuery();

the parameter "itemsPerPage" equals 10 and the result is

image

returns only two rows in the query, because it is counting queries to roles as if they were part of the main query

Please add a release tag

Hi there,

Is there anything I can do to persuade you to put a release tag on the latest commit of your project?

Thanks very much!

Error with DoctrineExtensions update, URGENT!

I have DoctrineExtensions - dev/master and IdeupSimplePaginator - dev/master and I'm getting this error message.

Attempted to load class "Paginate" from namespace "DoctrineExtensions\Paginate".
Did you forget a "use" statement for another namespace?
500 Internal Server Error - ClassNotFoundException

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.