Pagination for PHP.

Overview

NB This project is no longer maintained; you may like to use https://github.com/BabDev/Pagerfanta instead.

Pagerfanta

Build Status Scrutinizer Quality Score Code Coverage SensioLabsInsight Latest Stable Version Total Downloads

This project is for PHP 7. If you need support for PHP < 7, use Release v1.1.0.

Usage

<?php

use Pagerfanta\Adapter\ArrayAdapter;
use Pagerfanta\Pagerfanta;

$adapter = new ArrayAdapter($array);
$pagerfanta = new Pagerfanta($adapter);

$pagerfanta->setMaxPerPage($maxPerPage); // 10 by default
$maxPerPage = $pagerfanta->getMaxPerPage();

$pagerfanta->setCurrentPage($currentPage); // 1 by default
$currentPage = $pagerfanta->getCurrentPage();

$nbResults = $pagerfanta->getNbResults();
$currentPageResults = $pagerfanta->getCurrentPageResults();

Some of the other methods available:

$pagerfanta->getNbPages();
$pagerfanta->haveToPaginate(); // whether the number of results is higher than the max per page
$pagerfanta->hasPreviousPage();
$pagerfanta->getPreviousPage();
$pagerfanta->hasNextPage();
$pagerfanta->getNextPage();
$pagerfanta->getCurrentPageOffsetStart();
$pagerfanta->getCurrentPageOffsetEnd();

Changing the page based on user selection

If you're using the example route-generator function shown below, the page selected by the user will be available in the page GET (querystring) parameter.

You would then need to call setCurrentPage with the value of that parameter:

if (isset($_GET["page"])) {
    $pagerfanta->setCurrentPage($_GET["page"]);
}

setMaxPerPage and setCurrentPage

The ->setMaxPerPage() and ->setCurrentPage() methods implement a fluent interface:

<?php

$pagerfanta
    ->setMaxPerPage($maxPerPage)
    ->setCurrentPage($currentPage);

The ->setMaxPerPage() method throws an exception if the max per page is not valid:

  • Pagerfanta\Exception\NotIntegerMaxPerPageException
  • Pagerfanta\Exception\LessThan1MaxPerPageException

Both extend from Pagerfanta\Exception\NotValidMaxPerPageException.

The ->setCurrentPage() method throws an exception if the page is not valid:

  • Pagerfanta\Exception\NotIntegerCurrentPageException
  • Pagerfanta\Exception\LessThan1CurrentPageException
  • Pagerfanta\Exception\OutOfRangeCurrentPageException

All of them extend from Pagerfanta\Exception\NotValidCurrentPageException.

->setCurrentPage() throws an out ot range exception depending on the max per page, so if you are going to modify the max per page, you should do it before setting the current page.

(If you want to use Pagerfanta in a Symfony project, see https://github.com/whiteoctober/WhiteOctoberPagerfantaBundle.)

Adapters

The adapter's concept is very simple. An adapter just returns the number of results and an slice for a offset and length. This way you can adapt a pagerfanta to paginate any kind results simply by creating an adapter.

An adapter must implement the Pagerfanta\Adapter\AdapterInterface interface, which has these two methods:

<?php

/**
 * Returns the number of results.
 *
 * @return integer The number of results.
 */
function getNbResults();

/**
 * Returns an slice of the results.
 *
 * @param integer $offset The offset.
 * @param integer $length The length.
 *
 * @return array|\Iterator|\IteratorAggregate The slice.
 */
function getSlice($offset, $length);

Pagerfanta comes with these adapters:

ArrayAdapter

To paginate an array.

<?php

use Pagerfanta\Adapter\ArrayAdapter;

$adapter = new ArrayAdapter($array);

MongoAdapter

To paginate Mongo Cursors.

<?php

use Pagerfanta\Adapter\MongoAdapter;

$cursor = $collection->find();
$adapter = new MongoAdapter($cursor);

MandangoAdapter

To paginate Mandango Queries.

<?php

use Pagerfanta\Adapter\MandangoAdapter;

$query = $mandango->getRepository('Model\Article')->createQuery();
$adapter = new MandangoAdapter($query);

DoctrineDbalAdapter

To paginate DoctrineDbal query builders.

<?php

use Pagerfanta\Adapter\DoctrineDbalAdapter;
use Doctrine\DBAL\Query\QueryBuilder;

$queryBuilder = new QueryBuilder($conn);
$queryBuilder->select('p.*')->from('posts', 'p');

$countQueryBuilderModifier = function ($queryBuilder) {
    $queryBuilder->select('COUNT(DISTINCT p.id) AS total_results')
          ->setMaxResults(1);
};

$adapter = new DoctrineDbalAdapter($queryBuilder, $countQueryBuilderModifier);

DoctrineDbalSingleTableAdapter

To simplify the pagination of single table DoctrineDbal query builders.

This adapter only paginates single table query builders, without joins.

<?php

use Pagerfanta\Adapter\DoctrineDbalSingleTableAdapter;
use Doctrine\DBAL\Query\QueryBuilder;

$queryBuilder = new QueryBuilder($conn);
$queryBuilder->select('p.*')->from('posts', 'p');

$countField = 'p.id';

$adapter = new DoctrineDbalSingleTableAdapter($queryBuilder, $countField);

DoctrineORMAdapter

To paginate DoctrineORM query objects.

<?php

use Pagerfanta\Adapter\DoctrineORMAdapter;

$queryBuilder = $entityManager->createQueryBuilder()
    ->select('u')
    ->from('Model\Article', 'u');
$adapter = new DoctrineORMAdapter($queryBuilder);

DoctrineODMMongoDBAdapter

To paginate DoctrineODMMongoDB query builders.

<?php

use Pagerfanta\Adapter\DoctrineODMMongoDBAdapter;

$queryBuilder = $documentManager->createQueryBuilder('Model\Article');
$adapter = new DoctrineODMMongoDBAdapter($queryBuilder);

DoctrineODMPhpcrAdapter

To paginate Doctrine PHPCR-ODM query builders.

<?php

use Pagerfanta\Adapter\DoctrineODMPhpcrAdapter;

$queryBuilder = $documentManager->createQueryBuilder();
$queryBuilder->from('Model\Article');
$adapter = new DoctrineODMPhpcrAdapter($queryBuilder);

DoctrineCollectionAdapter

To paginate a Doctrine\Common\Collection\Collections interface you can use the DoctrineCollectionAdapter. It proxies to the count() and slice() methods on the Collections interface for pagination. This makes sense if you are using Doctrine ORMs Extra Lazy association features:

<?php

use Pagerfanta\Adapter\DoctrineCollectionAdapter;

$user = $em->find("Pagerfanta\Tests\Adapter\DoctrineORM\User", 1);

$adapter = new DoctrineCollectionAdapter($user->getGroups());

DoctrineSelectableAdapter

To paginate a Doctrine\Common\Collection\Selectable interface you can use the DoctrineSelectableAdapter. It uses the matching() method on the Selectable interface for pagination. This is especially usefull when using the Doctrine Criteria object to filter a PersistentCollection:

<?php

use Pagerfanta\Adapter\DoctrineSelectableAdapter;
use Doctrine\Common\Collections\Criteria;

$user = $em->find("Pagerfanta\Tests\Adapter\DoctrineORM\User", 1);
$comments = $user->getComments();
$criteria = Criteria::create()->andWhere(Criteria::expr()->in('id', array(1,2,3));

$adapter = new DoctrineSelectableAdapter($comments, $criteria);

Note that you should never use this adapter with a PersistentCollection which is not set to use the EXTRA_LAZY fetch mode.

Be careful when using the count() method, currently Doctrine2 needs to fetch all the records to count the number of elements.

ElasticaAdapter

To paginate an Elastica Query query:

<?php

use Elastica\Index;
use Elastica\Query;
use Elastica\Query\Term;
use Pagerfanta\Adapter\ElasticaAdapter;

// Searchable can be any valid searchable Elastica object. For example a Type or Index
$searchable = new Index($elasticaClient, 'index_name');
// A Query can be any valid Elastica query (json, array, Query object)
$query = new Query::create(new Term(array(
    'name' => 'Fred'
));

$adapter = new ElasticaAdapter($searchable, $query);

Be careful when paginating a huge set of documents. By default, offset + limit can't exceed 10000. You can mitigate this by setting the $maxResults parameter when constructing the ElasticaAdapter. For more information, see: #213.

PropelAdapter

To paginate a propel 1 query:

<?php

use Pagerfanta\Adapter\PropelAdapter;

$adapter = new PropelAdapter($query);

Propel2Adapter

To paginate a propel 2 query:

<?php

use Pagerfanta\Adapter\Propel2Adapter;

$adapter = new Propel2Adapter($query);

SolariumAdapter

To paginate a solarium query:

<?php

use Pagerfanta\Adapter\SolariumAdapter;

$query = $solarium->createSelect();
$query->setQuery('search term');

$adapter = new SolariumAdapter($solarium, $query);

FixedAdapter

Best used when you need to do a custom paging solution and don't want to implement a full adapter for a one-off use case.

It returns always the same data no matter what page you query:

<?php

use Pagerfanta\Adapter\FixedAdapter;

$nbResults = 5;
$results = array(/* ... */);

$adapter = new FixedAdapter($nbResults, $results);

ConcatenationAdapter

Concatenates the results of other adapter instances into a single adapter. It keeps the order of sub adapters and the order of their results.

<?php

use Pagerfanta\Adapter\ConcatenationAdapter;

$superAdapter = new ConcatenationAdapter(array($adapter1, $adapter2 /* ... */));

Views

Views are to render pagerfantas, this way you can reuse your pagerfantas' HTML in several projects, share them and use another ones from another developer's.

The views implement the Pagerfanta\View\ViewInterface interface, which has two methods:

<?php

/**
 * Renders a pagerfanta.
 *
 * The route generator is any callable to generate the routes receiving the page number
 * as first and unique argument.
 *
 * @param PagerfantaInterface $pagerfanta     A pagerfanta.
 * @param mixed               $routeGenerator A callable to generate the routes.
 * @param array               $options        An array of options (optional).
 */
function render(PagerfantaInterface $pagerfanta, $routeGenerator, array $options = array());

/**
 * Returns the canonical name.
 *
 * @return string The canonical name.
 */
function getName();

RouteGenerator example:

<?php

$routeGenerator = function($page) {
    return '/path?page='.$page;
};

Pagerfanta comes with five views: The default one, three for Twitter Bootstrap, one for Semantic UI and a special optionable view.

DefaultView

This is the default view.

<?php

use Pagerfanta\View\DefaultView;

$view = new DefaultView();
$options = array('proximity' => 3);
$html = $view->render($pagerfanta, $routeGenerator, $options);

Options (default):

  • proximity (3)
  • prev_message (Previous)
  • next_message (Next)
  • css_disabled_class (disabled)
  • css_dots_class (dots)
  • css_current_class (current)
  • dots_text (...)
  • container_template (%pages%)
  • page_template (%text%)
  • span_template (%text%)

CSS:

.pagerfanta {
}

.pagerfanta a,
.pagerfanta span {
    display: inline-block;
    border: 1px solid blue;
    color: blue;
    margin-right: .2em;
    padding: .25em .35em;
}

.pagerfanta a {
    text-decoration: none;
}

.pagerfanta a:hover {
    background: #ccf;
}

.pagerfanta .dots {
    border-width: 0;
}

.pagerfanta .current {
    background: #ccf;
    font-weight: bold;
}

.pagerfanta .disabled {
    border-color: #ccf;
    color: #ccf;
}

COLORS:

.pagerfanta a,
.pagerfanta span {
    border-color: blue;
    color: blue;
}

.pagerfanta a:hover {
    background: #ccf;
}

.pagerfanta .current {
    background: #ccf;
}

.pagerfanta .disabled {
    border-color: #ccf;
    color: #cf;
}

TwitterBootstrapView, TwitterBootstrap3View and TwitterBootstrap4View

These views generate paginators designed for use with Twitter Bootstrap.

TwitterBootstrapView is for Bootstrap 2; TwitterBootstrap3View is for Bootstrap 3; TwitterBootstrap4View is for Bootstrap 4 (alpha).

<?php

use Pagerfanta\View\TwitterBootstrapView;

$view = new TwitterBootstrapView();
$options = array('proximity' => 3);
$html = $view->render($pagerfanta, $routeGenerator, $options);

Options (default):

  • proximity (3)
  • prev_message (← Previous)
  • prev_disabled_href ()
  • next_message (Next →)
  • next_disabled_href ()
  • dots_message (…)
  • dots_href ()
  • css_container_class (pagination)
  • css_prev_class (prev)
  • css_next_class (next)
  • css_disabled_class (disabled)
  • css_dots_class (disabled)
  • css_active_class (active)

SemanticUiView

This view generates a pagination for Semantic UI.

<?php

use Pagerfanta\View\SemanticUiView;

$view = new SemanticUiView();
$options = array('proximity' => 3);
$html = $view->render($pagerfanta, $routeGenerator, $options);

Options (default):

  • proximity (3)
  • prev_message (← Previous)
  • prev_disabled_href ()
  • next_message (Next →)
  • next_disabled_href ()
  • dots_message (…)
  • dots_href ()
  • css_container_class (pagination)
  • css_item_class (item)
  • css_prev_class (prev)
  • css_next_class (next)
  • css_disabled_class (disabled)
  • css_dots_class (disabled)
  • css_active_class (active)

OptionableView

This view is to reuse options in different views.

<?php

use Pagerfanta\DefaultView;
use Pagerfanta\OptionableView;

$defaultView = new DefaultView();

// view and default options
$myView1 = new OptionableView($defaultView, array('proximity' => 3));

$myView2 = new OptionableView($defaultView, array('prev_message' => 'Anterior', 'next_message' => 'Siguiente'));

// using in a normal way
$pagerfantaHtml = $myView2->render($pagerfanta, $routeGenerator);

// overwriting default options
$pagerfantaHtml = $myView2->render($pagerfanta, $routeGenerator, array('next_message' => 'Siguiente!!'));

Contributing

We welcome contributions to this project, including pull requests and issues (and discussions on existing issues).

If you'd like to contribute code but aren't sure what, the issues list is a good place to start. If you're a first-time code contributor, you may find Github's guide to forking projects helpful.

All contributors (whether contributing code, involved in issue discussions, or involved in any other way) must abide by our code of conduct.

Acknowledgements

Pagerfanta is inspired by Zend Paginator.

Thanks also to Pablo Díez ([email protected]) for most of the work on the first versions of Pagerfanta.

Licence

Pagerfanta is licensed under the MIT License.

Comments
  • Doctrine ORM pagination improvements

    Doctrine ORM pagination improvements

    A bunch of improvements to the Doctrine ORM pagination.

    The CountWalker and LimitSubqueryWalker have been implemented using output walkers instead of tree walkers. The WhereInWalker has been extended. Improvements:

    • Support for more complex DQL queries using named mixed results with GROUP BY and HAVING. For example: SELECT g, u, COUNT(u.id) AS userCount FROM Entity\Group g LEFT JOIN g.users u GROUP BY g.id HAVING userCount > 0
    • Support for WHERE NOT queries
    • Better performance. The CountWalker and WhereInWalker use subselects. Most databases can cache subqueries individually, so it is possible to reuse the CountWalker result for the LimitSubqueryWalker. To prevent cache misses, the CountWalker no longer strips ORDER BY clauses.
    • Support for entities with composite primary keys in the CountWalker and LimitSqlWalker. Only the WhereInWalker still needs to be updated for full composite primary key support. But someone smarter than me needs to look at that and figure out how to build a WHERE IN query that can select rows based on multiple columns.

    CC: @Nico-B @pablodip @Seldaek

    opened by sandermarechal 18
  • Doctrine dbal adapter

    Doctrine dbal adapter

    This PR includes all commits from #48 and fixes all points that were pending in it.

    However, I figured out that the adapter is broken in the case of a join (and the expectation were wrong in the test). See the my third commit making the test fail. I will try finding a solution but maybe @mtotheikle has an idea ?

    opened by stof 15
  • Class or interface Pagerfanta\Boolean does not exist

    Class or interface Pagerfanta\Boolean does not exist

    https://github.com/whiteoctober/Pagerfanta/blob/f71a529c7a2711ec830396eb2bcc11d14ab0fde8/src/Pagerfanta/Pagerfanta.php#L65

    Hello! When i'm try to use psalm static analyzer, it produce an error.

    Class or interface Pagerfanta\Boolean does not exist

    Please can you use lowercase typehints, like in other methods. Because analyzer thinks it's PSR-4 classname (starts with capital letter).

    opened by demenkov 13
  • Count Performance of DoctrineORMAdapter COUNT query and large record sets

    Count Performance of DoctrineORMAdapter COUNT query and large record sets

    This issue is pertinent to Pagerfanta\Adapter\DoctrineORMAdapter.

    I've run into performance problems with the way that the 'count' part of the pagination query is being constructed as referenced in the following issues (across multiple projects) (using MySQL):

    https://github.com/KnpLabs/knp-components/pull/77 https://github.com/doctrine/doctrine2/pull/298 https://github.com/KnpLabs/knp-components/issues/65 https://github.com/KnpLabs/KnpPaginatorBundle/issues/202 https://github.com/beberlei/DoctrineExtensions/pull/59

    This issue will be relevant to anyone using the paginator with MySQL and anything approaching a large number of rows in a database (for me 80k) - when it can take > 100 seconds to execute the count part of the query on a modest amount of data.

    My goal here is to simplify the poorly performing query being generated, given that I'm not performing any join or group conditions (and I appreciate why the below structure may be required if this were the case), I have no need for either the 'distinct' subquery, nor the inner subquery it selects from. I'm trying to get from this:

    SELECT 
      COUNT(*) AS dctrn_count 
    FROM 
      (
        SELECT 
          DISTINCT id0 
        FROM 
          (
            SELECT 
              o0_.id AS id0, 
              o0_.ordr_id AS ordr_id1, 
              ...etc
            FROM 
              ordr_status o0_
            WHERE
              some_property = 'something'
          ) dctrn_result
      ) dctrn_table
    

    to this:

    SELECT COUNT(*) AS dctrn_count
        FROM ordr_status o0_
        WHERE some_property = 'something'
    

    or this (I don't care about the DISTINCT as it doesn't seem to hurt performance):

    SELECT COUNT(DISTINCT id0) AS dctrn_count
        FROM ordr_status o0_
        WHERE some_property = 'something'
    

    It seems the way to do this is to avoid using the 'Doctrine\ORM\Tools\Pagination\CountOutputWalker' within the Doctrine paginator.

    I've tried a variety of changing query walkers, query hints, and changing options in the paginator, and I've found I can achieve what I want by doing this in the DoctrineORMAdapter constructor:

    $this->paginator = new DoctrinePaginator($query, false);
    $this->paginator->setUseOutputWalkers(false);
    

    So: Could/Should the option to disable use of output walker be available in the adapter constructor:

    public function __construct($query, $fetchJoinCollection = true, $useOutputWalkers = true)
    {
        if (class_exists('Doctrine\ORM\Tools\Pagination\Paginator')) {
            $this->paginator = new DoctrinePaginator($query, $fetchJoinCollection);
            if (!$useOutputWalkers) {
              $this->paginator->setUseOutputWalkers(false);
            }
        } else {
            $this->paginator = new LegacyPaginator($query, $fetchJoinCollection);
        }
    }
    

    OR is there an alternative way to get this behaviour (such as setting a hint on the query before passing it to the adapter) that I've missed.

    opened by calumbrodie 12
  • Single id is not allowed

    Single id is not allowed

    I'm receiving this exception when trying to get current page results :

    Single id is not allowed on composite primary key in entity Nk\PlayerBundle\Entity\Message_Player

    I need theses 2 @id I've in my Entity @ManyToOne associations to other Entities.

    Can you help me ?

    Thanks!

    opened by Spriteware 11
  • subquery and not mapped field in order by

    subquery and not mapped field in order by

    hi,

    I try to use order by whit a not mapped field, like this :

    Select AVG(xxx) as alias From ... Where ... Order By alias

    in LimitSubqueryWalker : $item->expression->identificationVariable, $item->expression->field

    this properties dont exists for an order by whit not mapped field and make an error. But when I bypass the code (just for test) I have a SQLwalker error.

    Problem appear when we use fetch joined collections and not mapped field in order by, the subquery generation fail.

    opened by NicolasBadey 11
  • Looking for maintainers

    Looking for maintainers

    Hi,

    Sam here, one of the current maintainers of this project.

    Given that we no longer use PHP in our active projects, it's becoming harder to give this plugin the time it needs.

    Therefore, we're looking for new maintainer(s) for this project.

    We'd like any new prospective maintainer to fork this project, and then once that fork has moved forward enough to give us confidence in your ownership, we would link to your fork prominently from the top of the README here, encouraging others to use it instead.

    If you're interested, please go ahead and fork (if you haven't already) and start work! If you've forked and would like others to help you, feel free to reply in this issue with details of your fork.

    Please do reply here if you have questions. Thanks in anticipation.

    opened by sampart 9
  • Cannot define proximity to 0

    Cannot define proximity to 0

    The view option 'proximity' cannot be defined to 0. When defined to 0, It seems that the proximity is automatically pushed to 2. This is a really hard constraint to use pagerfanta on mobile templates...

    opened by aguerre 9
  • DoctrineORMAdapter Left Join & Order By

    DoctrineORMAdapter Left Join & Order By

    I don't know if this is a real issue, but I think must tell you.

    First, I use Pagerfanta on Symfony 2.0.X.

    The best way is an example, I use a query like this:

    $q = $em->createQueryBuilder();
    $q->select('a, b, c');
    $q->from('AcmeBundle:Aaa','a JOIN a.bbb b LEFT JOIN b.ccc c');
    $q->addOrderBy('c.foo', 'ASC');
    

    I use an "order by" in a field that is aggregate in an "left join".

    This cause the result of the query (that search the id's in the getIterator() method) add the "c.foo" field to the select stament, and this miss the distinct of a.id, because now the select stament is "DISTINCT a.id, c.foo" and this must be only "DISTINCT a.id".

    The problem is: id's obtained is a repetition of "a.id" for each "c.foo" distinct element, this break the count of the paginator.

    I think the query that search id's will be similar to the query that get the count (except the count function), only where clause's and one field on select stament.

    The order by clause is only required in the last query that get the final result (I think).

    opened by joseandrespg 9
  • Any easy way to output the paginator as json?

    Any easy way to output the paginator as json?

    Hi

    Is there any helper method to output the paginator properties in array or json format? similar to Zend Paginator toJson method with JsonSerializable support? my current workaround:

        public function toArray(Pagerfanta $pagerfanta)
        {
            $items = (array) $pagerfanta->getCurrentPageResults();
    
            return [
                'items'             => $items,
                'count_results'     => $pagerfanta->getNbResults(),
                'current_page'      => $pagerfanta->getCurrentPage(),
                'number_of_pages'   => $pagerfanta->getNbPages(),
                'next'              => ($pagerfanta->hasNextPage()) ? $pagerfanta->getNextPage() : null,
                'prev'              => ($pagerfanta->hasPreviousPage()) ? $pagerfanta->getPreviousPage() : null,
                'paginate'          => $pagerfanta->haveToPaginate(),
            ];
        }
    
    opened by zspine 8
  • Solarium Adapter Resultset

    Solarium Adapter Resultset

    The resultset in Solarium has additional methods to get things like the facetset. The visibility of getResultSet() is private which means you can't access these without doing another query.

    Perhaps just change the getResultSet() visibility to public?

    opened by joshuaadickerson 8
  • Doctrine dbal groupby

    Doctrine dbal groupby

    Sample usecase:

    $pager = new Pagerfanta(new DoctrineDbalAdapter($query, function (QueryBuilder $queryBuilder) {
        return $queryBuilder->getConnection()
            ->createQueryBuilder()
            ->select('COUNT(*) AS total')
            ->from('(' . $queryBuilder->getSQL()  . ')', 'QL')
            ->setMaxResults(1)
            ->setParameters($queryBuilder->getParameters());
    }));
    
    opened by tugrul 2
  • The MongoAdaptor does not work with modern MongoDB drivers

    The MongoAdaptor does not work with modern MongoDB drivers

    The current MongoAdaptor is based on the Depreciated php-mongo driver, all post v 7.x drivers are based on the php-mongodb driver that has a different access api

    opened by thawkins 0
  • Performance issue with serializer

    Performance issue with serializer

    We added this library to our api to pass in the results serialized to our UI, however, it seems like it does not work well with Symfony serializer. Any idea why? It’s cause slowness and performance issues. Seems like it’s not playing well with the serializer.

    opened by chris2kus31 0
  • Add adapter to support Mongo Aggregation Builder

    Add adapter to support Mongo Aggregation Builder

    Currently the DoctrineODMMongoDBAdapter only supports the Query Builder:

    • https://github.com/doctrine/mongodb-odm/blob/master/lib/Doctrine/ODM/MongoDB/Query/Builder.php

    But there is also the Aggregation Builder:

    • https://github.com/doctrine/mongodb-odm/blob/master/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php

    Adding an additional adapter based on the existing one is actually easy:

    use Doctrine\ODM\MongoDB\Aggregation\Builder;
    use Pagerfanta\Adapter\AdapterInterface;
    
    class DoctrineODMMongoDBAggregationAdapter implements AdapterInterface
    {
        private $aggregationBuilder;
    
        /**
         * Constructor.
         *
         * @param Builder $aggregationBuilder A DoctrineMongo aggregation builder.
         */
        public function __construct(Builder $aggregationBuilder)
        {
            $this->aggregationBuilder = $aggregationBuilder;
        }
    
        /**
         * Returns the query builder.
         *
         * @return Builder The query builder.
         */
        public function getAggregationBuilder()
        {
            return $this->aggregationBuilder;
        }
    
        /**
         * {@inheritdoc}
         */
        public function getNbResults()
        {
            return $this->aggregationBuilder->execute()->count();
        }
    
        /**
         * {@inheritdoc}
         */
        public function getSlice($offset, $length)
        {
            return $this->aggregationBuilder
                ->limit($length)
                ->skip($offset)
                ->execute();
        }
    }
    

    Unfortunately none of the two builders implement a common Interface. But there is another reason why using a single adapter for both use cases could be problematic!

    The aggregation builder uses a pipeline. Each time a so called "stage" e.g. limit oder sort is added the return value of the assigned variable changes.

    $qb = $this
        ->createAggregationBuilder();
        ->sort(['leavingDate' => 1])
        ->limit($query->limit);
    
    dump($qb); // Instance of Limit extends Stage
    
    $qb = $this
        ->createAggregationBuilder();
    $qb
        ->sort(['leavingDate' => 1])
        ->limit($query->limit);
    
    dump($qb); // Instance of Builder
    

    As soon as you pass a Stage instance you can not retrieve the original builder:

    • https://github.com/doctrine/mongodb/blob/master/lib/Doctrine/MongoDB/Aggregation/Stage.php#L19

    Also there are plans for ODM version 2 which may change this behaviour:

    • https://github.com/doctrine/mongodb-odm/pull/1856

    Maybe @alcaeus or @malarzm could comment on this too? Thanks in advance!

    Possibly related issues:

    • https://github.com/doctrine/mongodb-odm/issues/1988#issuecomment-478009400 @ychanan
    opened by webdevilopers 2
  • Offset support for `Pagerfanta`

    Offset support for `Pagerfanta`

    Problem

    • There was currently no way to have offset for pagerfanta :disappointed:

    Solution

    • Offset is now working and I also added simple test :smile:
    opened by matjaz321 1
  • I set the initial value of the First Result in query Builder. Why didn't I add Pagerfanta into the Offset when using Pagerfanta

    I set the initial value of the First Result in query Builder. Why didn't I add Pagerfanta into the Offset when using Pagerfanta

    public function getAuthorProducts($uuid)
    {
        $queryBuilder = $this->createQueryBuilder('o')
            ->addSelect('author')
            ->innerJoin('o.author', 'author')
            ->andWhere("author.uuid=:uuid")
            ->andWhere("o.enabled=:enabled")
            ->andWhere("o.isShow=:isShow")
            ->setParameter("isShow", true)
            ->setParameter("enabled", true)
            ->setParameter("uuid", $uuid)
            ->setFirstResult(5)
        ;
    
        return $this->getPaginator($queryBuilder);
    }
    

    I print the Paginator image

    Query Builder has FirstResult in it

    But FirstResult didn't work in the end

    I notice that "Pagerfanta/Pagerfanta, "line 316 is not going to fetch the initial FirstResult

    private function getCurrentPageResultsFromAdapter()
    {
        $offset = $this->calculateOffsetForCurrentPageResults();
        $length = $this->getMaxPerPage();
    
        return $this->adapter->getSlice($offset, $length);
    }
    
    private function calculateOffsetForCurrentPageResults()
    {
        return ($this->getCurrentPage() - 1) * $this->getMaxPerPage();
    }
    
    opened by tb07 1
Releases(v2.1.3)
  • v2.1.3(Jul 17, 2019)

    • [ElasticaAdapter] use count() instead search() for getNbResult() #280
    • Fixed: Attempted to call an undefined method named "count" of class " Doctrine\ODM\MongoDB\Query\Query". in DoctrineODMMongoDBAdapter #279
    Source code(tar.gz)
    Source code(zip)
  • v2.1.2(Apr 2, 2019)

  • v2.1.1(Mar 11, 2019)

  • v2.1.0(Feb 26, 2019)

    • Make Pagerfanta JsonSerializable (#269)

    Other changes:

    • Documentation improvements (#250, #258, #264, #265)
    • Move to PSR-4 autoloading (#260) and update phpunit requirements (#272)
    • Fix type annotations (#267)
    • Travis configuration changes (#270, #271)
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(May 17, 2018)

  • v2.0.0(May 1, 2018)

  • v1.1.0(May 1, 2018)

    New features

    • Add ConcatenationAdapter (#239)
    • Add method to identify which page the Nth item is on (#242)
    • Add support for options in ElasticaAdapter (#199)

    Fixes

    • Fix 'DefaultTemplate uses "previous_message" rather than "prev_message"' (#230)
    • Add contributor code of conduct (#233)
    • Various tweaks to tests (#236, #240)
    • Various README fixes (#231, #189, #187)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.5(Mar 20, 2017)

Owner
White October
White October
A simple helper to generate and display pagination navigation links

Intro to CHocoCode Paginator Friendly PHP paginator to paginate everything This package introduces a different way of pagination handling. You can rea

faso-dev 3 Aug 24, 2021
The Current US Version of PHP-Nuke Evolution Xtreme v3.0.1b-beta often known as Nuke-Evolution Xtreme. This is a hardened version of PHP-Nuke and is secure and safe. We are currently porting Xtreme over to PHP 8.0.3

2021 Nightly Builds Repository PHP-Nuke Evolution Xtreme Developers TheGhost - Ernest Allen Buffington (Lead Developer) SeaBeast08 - Sebastian Scott B

Ernest Buffington 7 Aug 28, 2022
A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

null 272 Dec 22, 2022
PHP Meminfo is a PHP extension that gives you insights on the PHP memory content

MEMINFO PHP Meminfo is a PHP extension that gives you insights on the PHP memory content. Its main goal is to help you understand memory leaks: by loo

Benoit Jacquemont 994 Dec 29, 2022
A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

null 258 Sep 15, 2022
A multithreaded application server for PHP, written in PHP.

appserver.io, a PHP application server This is the main repository for the appserver.io project. What is appserver.io appserver.io is a multithreaded

appserver.io 951 Dec 25, 2022
Easy to use utility functions for everyday PHP projects. This is a port of the Lodash JS library to PHP

Lodash-PHP Lodash-PHP is a port of the Lodash JS library to PHP. It is a set of easy to use utility functions for everyday PHP projects. Lodash-PHP tr

Lodash PHP 474 Dec 31, 2022
A PHP 5.3+ and PHP 7.3 framework for OpenGraph Protocol

Opengraph Test with Atoum cd Opengraph/ curl -s https://getcomposer.org/installer | php php composer.phar install --dev ./vendor/atoum/atoum/bin/atoum

Axel Etcheverry 89 Dec 27, 2022
A status monitor for Elite Dangerous, written in PHP. Designed for 1080p screens in the four-panel-view in panel.php, and for 7 inch screens with a resolution of 1024x600 connected to a Raspberry Pi.

EDStatusPanel A status monitor for Elite Dangerous, written in PHP. Designed for 1080p screens in the four-panel-view in panel.php, and for 7 inch scr

marcus-s 24 Oct 4, 2022
🐘 A probe program for PHP environment (一款精美的 PHP 探針, 又名X探針、劉海探針)

Simplified Chinese | 简体中文 Traditional Chinese(Taiwan) | 正體中文(臺灣) Traditional Chinese(Hong Kong) | 正體中文(香港) Japanese | 日本語 ?? X Prober This is a probe

Km.Van 1.2k Dec 28, 2022
PHP Text Analysis is a library for performing Information Retrieval (IR) and Natural Language Processing (NLP) tasks using the PHP language

php-text-analysis PHP Text Analysis is a library for performing Information Retrieval (IR) and Natural Language Processing (NLP) tasks using the PHP l

null 464 Dec 28, 2022
PHP generics written in PHP

PHP generics written in PHP Require PHP >= 7.4 Composer (PSR-4 Autoload) Table of contents How it works Quick start Example Features Tests How it work

Anton Sukhachev 173 Dec 30, 2022
PHP exercises from my course at ETEC and some of my own play-around with PHP

etec-php-exercises PHP exercises from my course at ETEC and some of my own play-around with PHP Translations: Português (BR) Projects Project Descript

Luis Felipe Santos do Nascimento 6 May 3, 2022
GitHub action to set up PHP with extensions, php.ini configuration, coverage drivers, and various tools.

GitHub action to set up PHP with extensions, php.ini configuration, coverage drivers, and various tools.

Shivam Mathur 2.4k Jan 6, 2023
php-echarts is a php library for the echarts 5.0.

php-echarts 一款支持Apache EChart5.0+图表的php开发库 优先ThinkPHP5/6的开发及测试。 Apache EChart5.0已经最新发布,在视觉效果、动画效果和大数据展示方面已经远超之前的版本; 故不考虑EChart5.0之前版本的兼容问题;建议直接尝试5.0+

youyiio 5 Aug 15, 2022
Minimalist PHP frame for Core-Library, for Developing PHP application that gives you the full control of your application.

LazyPHP lightweight Pre-Made Frame for Core-library Install Run the below command in your terminal $ composer create-project ryzen/lazyphp my-first-pr

Ry-Zen 7 Aug 21, 2022
Zilliqa PHP is a typed PHP-7.1+ interface to Zilliqa JSON-RPC API.

Zilliqa PHP is a typed PHP-7.1+ interface to Zilliqa JSON-RPC API. Check out the latest API documentation. Add library in a composer.json file.

Patrick Falize 6 Oct 7, 2021
churn-php is a package that helps you identify php files in your project that could be good candidates for refactoring

churn-php Helps discover good candidates for refactoring. Table of Contents What Is it? Compatibility How to Install? How to Use? How to Configure? Si

Bill Mitchell 1.3k Dec 22, 2022
Run your WP site on github pages, php innovation award winner https://www.phpclasses.org/package/12091-PHP-Make-a-WordPress-site-run-on-GitHub-pages.html

Gitpress Run wordpress directly on github pages Gitpress won the innovation award for may 2021 Read more about this https://naveen17797.github.io/gitp

naveen 13 Nov 18, 2022