Good day. There is a code that displays pagination on the site. But the fact is that it displays all links. For example, if I have 1000 entries in the database, the script will display 500 links per page (if there are 2 entries per page). Tell me, please, how to make it so that pagination displays pages 5, for example.

if (isset($_GET['page'])) { $CUR_PAGE=($_GET['page']); } else { $CUR_PAGE=1; } $res=mysql_query("SELECT count(*) FROM articles"); $row=mysql_fetch_row($res); $total_rows=$row[0]; $ITEM_PER_PAGE = 2; $start=abs(($CUR_PAGE-1)*$ITEM_PER_PAGE); $sql=mysql_query("SELECT * FROM articles ORDER BY id DESC LIMIT $start,$ITEM_PER_PAGE"); require_once 'tpl/index.php'; $uri=strtok($_SERVER['REQUEST_URI'],"?")."?"; if (isset($_GET['page'])) unset($_GET['page']); if (count($_GET)) { foreach ($_GET as $k => $v) { if ($k != "page") $uri.=urlencode($k)."=".urlencode($v)."&"; } } $num_pages=ceil($total_rows/$ITEM_PER_PAGE); for($i=1;$i<=$num_pages;$i++) $PAGES[$i]=$uri.'page='.$i; if ($CUR_PAGE <=1) { echo '<span>Prev</span>'; } else { $j = $CUR_PAGE - 1; echo '<a href="?page='.$j.'">Prev</a>'; } foreach ($PAGES as $i => $link) { if ($i == $CUR_PAGE) { echo '<b>'.$i.'</b>'; } else { echo '<a href="'.$link.'">'.$i.'</a>'; } } if ($CUR_PAGE == $num_pages) { echo '<span>Next</span>'; } else { $j = $CUR_PAGE + 1; echo '<a href="?page='.$j.'">Next</a>'; } if ($CUR_PAGE == $num_pages) { echo '<span>Last</span>'; } else { echo '<a href="?page='.$num_pages.'">Last</a>'; } 

    2 answers 2

    The task is simple and without using template engines and ready-made components, it can be solved as follows:

     $currentPage = 1; //текущая страница (CUR_PAGE) $maxPagesCount = 5; //общее количество страниц (num_pages) $paginatorHtmlContent = ''; //Переменная для хранения HTML кода паджинатора $minPage = max(1, $currentPage - 5); //Минимальная страница которую нужно вывести - 5 $maxPage = min($maxPagesCount, $currentPage + 5); //Максимальная страница от текущей + 5 for($i = $minPage;$i <= $maxPage;$i++) { if($maxPagesCount >= 1) { if($i === $currentPage) { $paginatorHtmlContent .= "<b>{$i}</b>"; } else { $paginatorHtmlContent .= "<a href='?page={$i}'>{$i}</a>"; } } } echo $paginatorHtmlContent; 

    I want to make some recommendations regarding your code:

    1. Stop using the mysql * extension, if this is a new project, go to newer libraries like PDO and mysqli;
    2. Discard the concatenation of variables received from the user in a database query, since with this approach, the probability of SQL injection is high;
    3. Name the variables in the same style;
    4. Begin to separate application data, user interface, and control logic. For example, you can try some kind of framework.
    • A small note: in your implementation, 5 + 1 pages will be shown at the edges of the range, and 5 + 1 + 5 in the middle. That is, the number of pages is not always the same. - Yegor Banin
    • @Firepro thank you very much. About the recommendations: Thank you for them. This is just a draft. But I will use some recommendations. - PigHead

    Well, it's easy! Take a moment from the sql and html. You have 500 pieces and you need to withdraw only 5 pieces.

     $limit = 5; for ($i = 0; $i < $limit; ++$i) { echo $i . "\n"; } 

    Not bad ah? Now you need to display 5 pieces not from the beginning but from the current position (half to the left, half to the right of the current position).

     $current = 15; $limit = 5; $from = $current - floor($limit / 2); for ($i = 0; $i < $limit; ++$i) { echo $from + $i . "\n"; } 

    Light! Only one thing is bad - $from may be <1 or> 500, but this would not be desirable.

     $all = 500; $current = 15; $limit = 5; $from = $current - floor($limit / 2); if ($from < 1) { $from = 1; } elseif ($from > $all - $limit + 1) { $from = $all - $limit + 1; } for ($i = 0; $i < $limit; ++$i) { echo $from + $i . "\n"; } 

    But it seems there was a mistake. What happens if $all < $limit ? It is necessary to fix it.

     $all = 4; $current = 3; $limit = min($all, 5); $from = $current - floor($limit / 2); if ($from < 1) { $from = 1; } elseif ($from > $all - $limit + 1) { $from = $all - $limit + 1; } for ($i = 0; $i < $limit; ++$i) { echo $from + $i . "\n"; } 

    Well, do not forget that you do not need to immediately make an echo , it is usually convenient to collect some Pagination object, which can then be iterated into a template.

    • Painted everything as a little. Thank you very much. Yes, when I save my system, I will simplify it with functions and classes. - PigHead
    • @PigHead is for illustrating a search for a solution. Understanding how to do often comes in the process, rather than being born immediately. From simple to more complex. - Yegor Banin
    • You are right, I understood everything, thanks, once again. Only here the error comes out. I put in $ limit "3", and when I am on the last page, non-existent links are added to the pagination. But if you put "2" in $ limit, then there is no such bug. As I understand it, this bug will be only with odd numbers? - PigHead pm
    • @PigHead and for which $ all, $ current there is a bug? By the way, Firepro proposes a solution that may be simpler to read. - Yegor Banin
    • Yegor, yes for any, actually. In addition to the mentioned two in $ limit. Any other value follows the bug. Well, yes, I also think that it is easier for him. But also about their own minuses that you noticed. But this condition can be corrected, I think. - PigHead 1:28 pm