How to generate pagination links with limits?

Asked

Viewed 1,033 times

6

I have a pagination whose results generate large amount of links-numbers.

Setting:

  • have 10.000 (ten thousand) records being paginated.

  • The pagination should be 30 in 30;

  • However, links cannot display 333 links, but only 15. And these links, are dynamically displayed according to the current page.

Example:

1 .. 15

16 .. 30

30 .. 40

317 ... 333

But I wish to do so, leaving the current page "in the middle" of these links.

Example:

 Página 35 exibe de 28 à 43

If I click 320.

317 ... 333

How could I do this in PHP?

Observing: I already managed to do this in Laravel 4, but I think the question will help some people who have this difficulty (and who do not use a framework).

Example of paging with dots on the links in Laravel 4:

@for ($i = $initial = max(1, $paginator->getCurrentPage() - 15), $l = min($initial + 20, $paginator->getLastPage()); $i <= $l; $i++)

    @if($paginator->getCurrentPage() == $i)
        <a class="item active">{{ $i }}</a>
    @else
        <a href="{{ $paginator->getUrl($i) }}">{{ $i }}</a>
    @endif

@endfor
  • http://stackoverflow.com/questions/11272108/logic-behind-pagination-like-google

  • Do I reward or not reward? Here’s the question!

  • No need... I just informed a link of a reply already given here mmesmo

  • @Jeffersonsilva right here? stack overflow != stack overflow

2 answers

1


I eventually decided to publish my own reply.

I created a function to generate a range of numbers according to the limit passed.

The logic is this: if I have 55 pages and I want to limit to 10. Will be shown 5 items before and 5 after the current page. If the current page is the initial value it is 1, the 5 which should be displayed before 1 are added at the end. If the limit value is 55, then we show off 10 before 55 (that is to say 45).

The idea is that the results got like this:

[1] 2 3 4 5 6 7 8 9 10
1 [2] 3 4 5 6 7 8 9 10
1 2 [3] 4 5 6 7 8 9 10
1 2 3 [4] 5 6 7 8 9 10
1 2 3 4 [5] 6 7 8 9 10
1 2 3 4 5 [6] 7 8 9 10
2 3 4 5 6 [7] 8 9 10 11
3 4 5 6 7 [8] 9 10 11 12

44 45 46 47 48 [49] 50 51 52 53 54
45 46 47 48 49 [50] 51 52 53 54 55 
45 46 47 48 49 50 [51] 52 53 54 55  
45 46 47 48 49 50 51 [52] 53 54 55

45 46 47 48 49 50 51 52 53 54 [55] 

For this I created the following function:

/**
 * @param int $current Página atual
 * @param int $total Total da Paginação
 * @param int $limit Limite de links exibidos
 * @param int $start_at Valor inicial. Geralmente o Padrão é 1
 * @return \Generator
 */
function range_limit($current, $total, $limit = 10, $start_at = 1)
{
    $middle = ceil($limit / 2);

    $current = max($start_at, min($total, $current));

    $start = $current - $middle;

    $end = $middle + $current;

    if ($start <= $start_at) {
        $start = $start_at;
        $end = $limit;

    } elseif ($end >= $total) {
        $end = $total;
        $start = $total - $limit;
    }

    for ($i = $start; $i <= $end; $i++) yield $i;
}

To use, just do so:

  range_limit($pagina_atual, $ultima_pagina, $limite_de_links);

See working on Ideone.

In a case closer to the real, it could look like this:

 $pagina_atual = $_GET['pagina'] ?? 1;

 $limite_da_paginacao = 15;

 // Se for 1, é 0
 // Se for 2, é 15
 // Se for 3, é 30
 // Se for 4, é 45
 $offset = ($pagina_atual * $limite_da_paginacao) - $limite_da_paginacao;

 $resultado = query("SELECT COUNT(*) as total FROM usuarios")->primeiro();

 $ultima_pagina = ceil($resultado->total / $limite_da_paginacao);

 $limite_de_links = 10;

 $dados = query("SELECT * FROM usuarios LIMIT ? OFFSET ?", $limite, $offset)->todos();

To generate links, just do:

  <?php foreach(range_limit($pagina_atual, $ultima_pagina, $limite_de_links) as $pagina): ?>
      <a href="index.php?pagina=<?=$pagina?>"><?= $pagina ?></a>
  <?php endforeach ?>

-1

As the question is quoted that the answer should provide a solution for beginner users, so I tried to make the simplest example possible, with the simplest calculation I could think of.

Step by step

Paging is the process of separating many results from some search, so it is mandatory to have an object to be manipulated in that pagination. In the example this object is a array simple of string where each string represents a page (whether an article, or a list of products, etc).

Another thing we should take into consideration is to safeguard the current page the user is on, the demo uses the GET of PHP to store and enter the current page value to the user.

The last thing is to think about the goal, which is to not only display the content of the selected page, it shows the link to X previous pages and X back pages of the current page. We soon defined some variables, such as:

  • display - which stores the value defined as the maximum quantity of links of pages.
  • middle - which is only the previous variable divided by 2 for inform how many pages before and after the current page we will fetch.

After becoming aware of the requirements to make such a pagination, we go to the code:

pager.php:

<?php
// array que simula o objeto a ser paginado, que normalmente é resultado de uma busca na persistência
$pages = array
(
    'page01', 'page02', 'page03', 'page04', 'page05',
    'page06', 'page07', 'page08', 'page09', 'page10',
    'page11', 'page12', 'page13', 'page14', 'page15',
    'page16', 'page17', 'page18', 'page19', 'page20',
    'page21', 'page22', 'page23', 'page24', 'page25',
    'page26', 'page27', 'page28', 'page29', 'page30',
);

// Resgata número página atual da URL, o padrão é 1
$current = isset($_GET['page']) ? $_GET['page'] : 1;

// Informa número de links para navegação de páginas a ser mostrado
// de preferência ser ímpar, para que possa haver um meio exato para página atual
$display = 7;

// se a página existir
if(array_key_exists($current - 1, $pages)):
    // exibe conteúdo da mesma
    echo "<h1>Current page: {$pages[$current - 1]}</h1>";

    // define o meio dos links, defino um contador com o mesmo valor
    // ele auxiliara na hora de mandar x links para direito e x para esquerda
    $middle = $cont = (int)($display/2);

    // Percorre de 0 até o limite de links
    for($pg = 0; $pg < $display; $pg ++):
        // Se não é o meio da quantidade de links
        if($pg != $middle)
        {
            // Se for uma página anterior
            if($pg < $middle)
            {
                // Página será igual a atual menos o contador
                $page = $current - $cont;
                // Decrementa contador, para que a proxima pagina seja +1
                $cont --;
            }
            // Se for uma página posterior
            else if($pg > $middle)
            {
                // Define numero da página, como atual + contador + 1 (que indica que já passou a página atual também)
                $page = $current + $cont + 1;
                // Incrementa contador, para que a proxima pagina seja +1
                $cont ++;
            }
            // Exibe o link apenas se a página tiver no intervalo de resultados
            if($page > 0 and $page <= count($pages))
                echo "<a href='pager.php?page={$page}'>{$page}</a> | ";
        }
        // Se for a página atual (estará no meio)
        else
        {
            // Exibe o link em negrito
            echo "<strong><a href='pager.php?page={$current}'>{$current}</a></strong> | ";
        }
    endfor;
// Se a página não existir
else:
    echo "<h1>Page not exists!</h1>";
endif;

?>
  • I’m a beginner in php, I didn’t understand the GET['page'], initial part, where it says the default is 1, but the naming of the array values is as "01"... Can you give me a brief clarification ?

  • @Magichat On the line I look, if there is get parameter, if yes I store get value in Current, if I do not store the number one, assuming that the first page is 1. In the array are just examples of content, Voce can edit it normally, what matters in the case is the key of the array that in the case goes from 0 until 29, where zero humanizing, means page 1, and so on until page 30. The contents of the array element would be the page text, nothing else. I hope to have clarified in this brief text.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.