How to generate links to bound pagination?

6

I have a page whose results generate a lot of links-numbers.

Scenery:

  • I have 10.000 (ten thousand) records being paged.

  • Paging should be 30 in 30 ;

  • However, links can not 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 want to do this by leaving the current page "in the middle" of those links.

Example:

 Página 35 exibe de 28 à 43

If I click 320.

317 ... 333

How could I do this in PHP?

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

Example of dotted pages on 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
    
asked by anonymous 27.07.2015 / 20:45

2 answers

1

I ended up deciding to publish my own answer.

I have created a function to be able to generate a range of numbers according to the last limit.

The logic is this: If I have 55 pages and I want to limit the 10 . 5 items before and 5 will be displayed after the current page. If the current page is the initial value that is 1 , the 5 that should be displayed before 1 is appended to the end. If the limit value is 55 , then we display 10 before 55 (or 45 ).

The idea is that the results look 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 have 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 the following:

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

See working at 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 the 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 ?>
    
23.08.2018 / 20:56
-1

As the question is quoted that the answer should provide a solution for beginning users, then I tried to make the simplest possible example 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 paging. In the example this object is a array simple of string where each string represents a page (be it an article, or list of products, etc.).

Another thing to keep in mind is to save the current page the user is in, the demonstration uses GET of PHP to store and inform the user of the current page value.

The last thing is to think about the goal, which is in addition to displaying the contents of the selected page, shows the link to X previous pages and X later pages of the current page. We soon define some variables, such as:

  • display - which stores the value defined as the maximum amount of page links.
  • middle - which is just the previous variable divided by 2 for how many pages before and after the current page we will go search.

After learning the requirements to do such pagination, we start with 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;

?>
    
21.07.2016 / 20:01