Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ttskch/TtskchPaginatorBundle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TtskchPaginatorBundle

Latest Stable Version Total Downloads

The most thin and simple paginator bundle for Symfony.

Features

  • So light weight
  • Depeds on nothing without Symfony
  • But also easy to use with Doctrine ORM
  • Customizable twig-templated views
  • Sortable link feature
  • Easy to use with search form
  • Preset Bootstrap4/5 theme

Requirement

  • PHP >=7.1.3
  • Symfony ^4.0|^5.0|^6.0

Demo

👉 Live demo is here

You can also see a sample code on demo branch.

Installation

$ composer require ttskch/paginator-bundle
// config/bundles.php

return [
    // ...
    Ttskch\PaginatorBundle\TtskchPaginatorBundle::class => ['all' => true],
];

Basic usages

With Doctrine ORM

// FooController.php

use Ttskch\PaginatorBundle\Context;
use Ttskch\PaginatorBundle\Doctrine\Counter;
use Ttskch\PaginatorBundle\Doctrine\Slicer;

public function index(FooRepository $fooRepository, Context $context)
{
    $qb = $fooRepository->createQueryBuilder('f');
    $context->initialize('id', new Slicer($qb), new Counter($qb));

    return $this->render('index.html.twig', [
        'foos' => $context->slice,
    ]);
}
{# index.html.twig #}

<table>
  <thead>
  <tr>
    <th>{{ ttskch_paginator_sortable('id') }}</th>
    <th>{{ ttskch_paginator_sortable('name') }}</th>
    <th>{{ ttskch_paginator_sortable('email') }}</th>
  </tr>
  </thead>
  <tbody>
  {% for foo in foos %}
    <tr>
      <td>{{ foo.id }}</td>
      <td>{{ foo.name }}</td>
      <td>{{ foo.email }}</td>
    </tr>
  {% endfor %}
  </tbody>
</table>

{{ ttskch_paginator_pager() }}

See src/Twig/TtskchPaginatorExtension.php to learn more about twig functions.

Sort with property of joined entity

Just do like as following.

{# index.html.twig #}

{# ... #}

<th>{{ ttskch_paginator_sortable('id') }}</th>
<th>{{ ttskch_paginator_sortable('name') }}</th>
<th>{{ ttskch_paginator_sortable('email') }}</th>
<th>{{ ttskch_paginator_sortable('bar.id', 'Bar') }}</th>
<th>{{ ttskch_paginator_sortable('bar.baz.id', 'Baz') }}</th>

{# ... #}

With array

Implement slicer and counter by yourself like as following.

// FooController.php

use Ttskch\PaginatorBundle\Context;
use Ttskch\PaginatorBundle\Entity\Criteria;

public function index(Context $context)
{
    $array = [
        ['id' => 1, 'name' => 'Tommy Yount', 'email' => '[email protected]'],
        ['id' => 2, 'name' => 'Hye Panter', 'email' => '[email protected]'],
        ['id' => 3, 'name' => 'Vi Yohe', 'email' => '[email protected]'],
        ['id' => 4, 'name' => 'Keva Bandy', 'email' => '[email protected]'],
        ['id' => 5, 'name' => 'Hannelore Corning', 'email' => '[email protected]'],
        ['id' => 6, 'name' => 'Delorse Whitcher', 'email' => '[email protected]'],
        ['id' => 7, 'name' => 'Katharyn Marrinan', 'email' => '[email protected]'],
        ['id' => 8, 'name' => 'Jeannine Tope', 'email' => '[email protected]'],
        ['id' => 9, 'name' => 'Jamila Braggs', 'email' => '[email protected]'],
        ['id' => 10, 'name' => 'Eden Cunniff', 'email' => '[email protected]'],
        // ...
        ['id' => 299, 'name' => 'Deshawn Kennedy', 'email' => '[email protected]'],
        ['id' => 300, 'name' => 'Elenore Evens', 'email' => '[email protected]'],
    ];
    
    $context->initialize(
        'id',
        function (Criteria $criteria) use ($array) {
            return array_slice($array, $criteria->limit * ($criteria->page -1), $criteria->limit)
        },
        function () use ($array) {
            return count($array);
        }
    );

    return $this->render('index.html.twig', [
        'foos' => $context->slice,
    ]);
}

Configuring

$ bin/console config:dump-reference ttskch_paginator
# Default configuration for extension with alias: "ttskch_paginator"
ttskch_paginator:
    page:
        name:                 page
        range:                5
    limit:
        name:                 limit
        default:              10
    sort:
        key:
            name:                 sort
        direction:
            name:                 direction

            # "asc" or "desc"
            default:              asc
    template:
        pager:                '@TtskchPaginator/pager/default.html.twig'
        sortable:             '@TtskchPaginator/sortable/default.html.twig'

Customizing views

Using preset Bootstrap4/5 theme

Just configure bundle like below.

# config/packages/ttskch_paginator.yaml

ttskch_paginator:
  template:
    pager: '@TtskchPaginator/pager/bootstrap5.html.twig'
#   pager: '@TtskchPaginator/pager/bootstrap4.html.twig'

Using your own theme

Create your own templates and configure bundle like below.

# config/packages/ttskch_paginator.yaml

ttskch_paginator:
  template:
    pager: 'your/own/pager.html.twig'
    sortable: 'your/own/sortable.html.twig'

Using with search form

// FooCriteria.php

use Ttskch\PaginatorBundle\Entity\AbstractCriteria;

class FooCriteria extends AbstractCriteria
{
    public $sort = 'id';
    public $query;

    public function getFormTypeClass(): ?string
    {
        return FooSearchType::class;
    }
}
// FooSearchType.php

use Symfony\Component\Form\Extension\Core\Type\SearchType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Ttskch\PaginatorBundle\Form\CriteriaType;

class FooSearchType extends CriteriaType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder
            ->add('query', SearchType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => FooCriteria::class,
            // if your app depends on symfony/security-csrf adding below is recommended
            // 'csrf_protection' => false,
        ]);
    }
}
// FooRepository.php

use Ttskch\PaginatorBundle\Doctrine\Counter;
use Ttskch\PaginatorBundle\Doctrine\Slicer;

public function sliceByCriteria(FooCriteria $criteria)
{
    $qb = $this->createQueryBuilderFromCriteria($criteria);
    $slicer = new Slicer($qb);

    return $slicer($criteria);
}

public function countByCriteria(FooCriteria $criteria)
{
    $qb = $this->createQueryBuilderFromCriteria($criteria);
    $counter = new Counter($qb);

    return $counter($criteria);
}

private function createQueryBuilderFromCriteria(FooCriteria $criteria)
{
    return $this->createQueryBuilder('f')
        ->orWhere('f.name like :query')
        ->orWhere('f.email like :query')
        ->setParameter('query', '%'.str_replace('%', '\%', $criteria->query).'%')
    ;
}
// FooController.php

public function index(FooRepository $fooRepository, Context $context)
{
    $context->initialize(
        null,
        [$fooRepository, 'sliceByCriteria'],
        [$fooRepository, 'countByCriteria'],
        new FooCriteria()
    );

    return $this->render('index.html.twig', [
        'foos' => $context->slice,
        'form' => $context->form->createView(),
    ]);
}
{# index.html.twig #}

{{ form(form, {action: path('foo_index'), method: 'get'}) }}

<table>
    <thead>
    <tr>
        <th>{{ ttskch_paginator_sortable('id') }}</th>
        <th>{{ ttskch_paginator_sortable('name') }}</th>
        <th>{{ ttskch_paginator_sortable('email') }}</th>
    </tr>
    </thead>
    <tbody>
    {% for foo in foos %}
        <tr>
            <td>{{ foo.id }}</td>
            <td>{{ foo.name }}</td>
            <td>{{ foo.email }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

{{ ttskch_paginator_pager() }}

Using with joined query

// FooRepository.php

use Ttskch\PaginatorBundle\Doctrine\Counter;
use Ttskch\PaginatorBundle\Doctrine\Slicer;

public function sliceByCriteria(FooCriteria $criteria)
{
    $qb = $this->createQueryBuilderFromCriteria($criteria);
    $slicer = new Slicer($qb);

    return $slicer($criteria, $alreadyJoined = true); // *
}

public function countByCriteria(FooCriteria $criteria)
{
    $qb = $this->createQueryBuilderFromCriteria($criteria);
    $counter = new Counter($qb);

    return $counter($criteria);
}

private function createQueryBuilderFromCriteria(FooCriteria $criteria)
{
    return $this->createQueryBuilder('f')
        ->leftJoin('f.bar', 'bar')
        ->leftJoin('bar.baz', 'baz')
        ->orWhere('f.name like :query')
        ->orWhere('f.email like :query')
        ->orWhere('bar.name like :query')
        ->orWhere('baz.name like :query')
        ->setParameter('query', '%'.str_replace('%', '\%', $criteria->query).'%')
    ;
}
// FooController.php

public function index(FooRepository $fooRepository, Context $context)
{
    $context->initialize(
        'f.id',
        [$fooRepository, 'sliceByCriteria'],
        [$fooRepository, 'countByCriteria'],
        new FooCriteria()
    );

    return $this->render('index.html.twig', [
        'foos' => $context->slice,
        'form' => $context->form->createView(),
    ]);
}
{# index.html.twig #}

{{ form(form, {action: path('foo_index'), method: 'get'}) }}

<table>
    <thead>
    <tr>
        <th>{{ ttskch_paginator_sortable('f.id', 'Id') }}</th>
        <th>{{ ttskch_paginator_sortable('f.name', 'Name') }}</th>
        <th>{{ ttskch_paginator_sortable('f.email', 'Email') }}</th>
        <th>{{ ttskch_paginator_sortable('bar.name', 'Bar') }}</th>
        <th>{{ ttskch_paginator_sortable('baz.name', 'Baz') }}</th>
    </tr>
    </thead>
    <tbody>
    {% for foo in foos %}
        <tr>
            <td>{{ foo.id }}</td>
            <td>{{ foo.name }}</td>
            <td>{{ foo.email }}</td>
            <td>{{ foo.bar.name }}</td>
            <td>{{ foo.bar.baz.name }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

{{ ttskch_paginator_pager() }}

About

The most thin, simple and customizable paginator bundle for Symfony.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •