php 智能分页算法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/163809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Smart pagination algorithm
提问by jeannicolas
I'm looking for an example algorithm of smart pagination. By smart, what I mean is that I only want to show, for example, 2 adjacent pages to the current page, so instead of ending up with a ridiculously long page list, I truncate it.
我正在寻找智能分页的示例算法。聪明,我的意思是我只想显示,例如,与当前页面相邻的 2 个页面,因此我不会以可笑的长页面列表结束,而是将其截断。
Here's a quick example to make it clearer... this is what I have now:
这是一个简单的例子,可以更清楚地说明......这就是我现在所拥有的:
Pages: 1 2 3 4 [5] 6 7 8 9 10 11
This is what I want to end up with:
这就是我想要的结果:
Pages: ... 3 4 [5] 6 7 ...
(In this example, I'm only showing 2 adjacent pages to the current page)
(在这个例子中,我只显示与当前页面相邻的 2 个页面)
I'm implementing it in PHP/Mysql, and the "basic" pagination (no trucating) is already coded, I'm just looking for an example to optimize it... It can be an example in any language, as long as it gives me an idea as to how to implement it...
我正在 PHP/Mysql 中实现它,并且“基本”分页(无截断)已经编码,我只是在寻找一个例子来优化它......它可以是任何语言的例子,只要它让我对如何实现它有了一个想法......
采纳答案by changelog
I had the same need a while ago.
不久前我也有同样的需求。
Here's the article I used to get it done (with PHP code): Digg-Style Pagination
这是我用来完成它的文章(使用 PHP 代码): Digg-Style Pagination
It works pretty fast and has some additions to what you're trying to do, like:
它的工作速度非常快,并且对您要执行的操作有一些补充,例如:
[1] 2 3 4 5 6 ... 100 1 [2] 3 4 5 6 ... 100 ... 1 ... 4 5 [6] 7 8 ... 100
Here is the code from the broken link:
这是来自断开链接的代码:
<?php
/*
Place code to connect to your DB here.
*/
// How many adjacent pages should be shown on each side?
$adjacents = 3;
/*
First get total number of rows in data table.
If you have a WHERE clause in your query, make sure you mirror it here.
*/
$query = "SELECT COUNT(*) as num FROM portfolio";
$total_pages = mysql_fetch_array(mysql_query($query));
$total_pages = $total_pages[num];
/* Setup vars for query. */
$limit = 2; //how many items to show per page
if($page)
$start = ($page - 1) * $limit; //first item to display on this page
else
$start = 0; //if no page var is given, set start to 0
/* Get data. */
$query = "SELECT category, uname, title FROM portfolio LIMIT $start, $limit";
$portfolio = mysql_query($query);
/* Setup page vars for display. */
if ($page == 0) $page = 1; //if no page var is given, default to 1.
$prev = $page - 1; //previous page is page - 1
$next = $page + 1; //next page is page + 1
$lastpage = ceil($total_pages/$limit); //lastpage is = total pages / items per page, rounded up.
$lpm1 = $lastpage - 1; //last page minus 1
/*
Now we apply our rules and draw the pagination object.
We're actually saving the code to a variable in case we want to draw it more than once.
*/
$pagination = "";
if($lastpage > 1)
{
$pagination .= "<div class="\"pagination\"">";
//previous button
if ($page > 1)
$pagination.= "<a href="\"diggstyle.php?page=$prev\"">? previous</a>";
else
$pagination.= "<span class="\"disabled\"">? previous</span>";
//pages
if ($lastpage < 7 + ($adjacents * 2)) //not enough pages to bother breaking it up
{
for ($counter = 1; $counter <= $lastpage; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
}
elseif($lastpage > 5 + ($adjacents * 2)) //enough pages to hide some
{
//close to beginning; only hide later pages
if($page < 1 + ($adjacents * 2))
{
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
$pagination.= "...";
$pagination.= "<a href="\"diggstyle.php?page=$lpm1\"">$lpm1</a>";
$pagination.= "<a href="\"diggstyle.php?page=$lastpage\"">$lastpage</a>";
}
//in middle; hide some front and some back
elseif($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2))
{
$pagination.= "<a href="\"diggstyle.php?page=1\"">1</a>";
$pagination.= "<a href="\"diggstyle.php?page=2\"">2</a>";
$pagination.= "...";
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
$pagination.= "...";
$pagination.= "<a href="\"diggstyle.php?page=$lpm1\"">$lpm1</a>";
$pagination.= "<a href="\"diggstyle.php?page=$lastpage\"">$lastpage</a>";
}
//close to end; only hide early pages
else
{
$pagination.= "<a href="\"diggstyle.php?page=1\"">1</a>";
$pagination.= "<a href="\"diggstyle.php?page=2\"">2</a>";
$pagination.= "...";
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
}
}
//next button
if ($page < $counter - 1)
$pagination.= "<a href="\"diggstyle.php?page=$next\"">next ?</a>";
else
$pagination.= "<span class="\"disabled\"">next ?</span>";
$pagination.= "</div>\n";
}
?>
<ul>
<?php
while($item = mysql_fetch_array($portfolio))
{
?>
<li><a href="/web/20080709045706/http://www.strangerstudios.com/portfolio//"></a></li>
<?php
}
?>
</ul>
<?=$pagination?>
回答by Alix Axel
Kinda late =), but here is my go at it:
有点晚了 =),但这是我的目标:
function Pagination($data, $limit = null, $current = null, $adjacents = null)
{
$result = array();
if (isset($data, $limit) === true)
{
$result = range(1, ceil($data / $limit));
if (isset($current, $adjacents) === true)
{
if (($adjacents = floor($adjacents / 2) * 2 + 1) >= 1)
{
$result = array_slice($result, max(0, min(count($result) - $adjacents, intval($current) - ceil($adjacents / 2))), $adjacents);
}
}
}
return $result;
}
Example:
例子:
$total = 1024;
$per_page = 10;
$current_page = 2;
$adjacent_links = 4;
print_r(Pagination($total, $per_page, $current_page, $adjacent_links));
Output (@ Codepad):
输出(@键盘):
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Another example:
另一个例子:
$total = 1024;
$per_page = 10;
$current_page = 42;
$adjacent_links = 4;
print_r(Pagination($total, $per_page, $current_page, $adjacent_links));
Output (@ Codepad):
输出(@键盘):
Array
(
[0] => 40
[1] => 41
[2] => 42
[3] => 43
[4] => 44
)
回答by Edwin
I started from the lazaro's post and tried to make a robust and light algorithm with javascript/jquery... No additional and/or bulky pagination libraries needed... Look on fiddle for an live example: http://jsfiddle.net/97JtZ/1/
我从 lazaro 的帖子开始,并尝试使用 javascript/jquery 制作一个健壮而轻便的算法......不需要额外的和/或庞大的分页库......在小提琴上查看一个活生生的例子:http: //jsfiddle.net/ 97JtZ/1/
var totalPages = 50, buttons = 5;
var currentPage = lowerLimit = upperLimit = Math.min(9, totalPages);
//Search boundaries
for (var b = 1; b < buttons && b < totalPages;) {
if (lowerLimit > 1 ) { lowerLimit--; b++; }
if (b < buttons && upperLimit < totalPages) { upperLimit++; b++; }
}
//Do output to a html element
for (var i = lowerLimit; i <= upperLimit; i++) {
if (i == currentPage) $('#pager').append('<li>' + i + '</li> ');
else $('#pager').append('<a href="#"><li><em>' + i + '</em></li></a> ');
}
回答by lazaro
List<int> pages = new List<int>();
int pn = 2; //example of actual pagenumber
int total = 8;
for(int i = pn - 9; i <= pn + 9; i++)
{
if(i < 1) continue;
if(i > total) break;
pages.Add(i);
}
return pages;
回答by Jacob
I made a pagination class and put in on Google Code a while ago. Check it out its pretty simple http://code.google.com/p/spaceshipcollaborative/wiki/PHPagination
我做了一个分页类,并在不久前加入了谷歌代码。看看它很简单 http://code.google.com/p/spaceshipcollaborative/wiki/PHPagination
$paging = new Pagination();
$paging->set('urlscheme','class.pagination.php?page=%page%');
$paging->set('perpage',10);
$paging->set('page',15);
$paging->set('total',3000);
$paging->set('nexttext','Next Page');
$paging->set('prevtext','Previous Page');
$paging->set('focusedclass','selected');
$paging->set('delimiter','');
$paging->set('numlinks',9);
$paging->display();
回答by Fernando Barrocal
I would use something simple on the page you are showing the paginator, like:
我会在您显示分页器的页面上使用一些简单的内容,例如:
if (
$page_number == 1 || $page_number == $last_page ||
$page_number == $actual_page ||
$page_number == $actual_page+1 || $page_number == $actual_page+2 ||
$page_number == $actual_page-1 || $page_number == $actual_page-2
) echo $page_number;
You can adapt it to show each 10 or so pages with %operator ...
您可以调整它以显示每 10 页左右的%操作符...
I think using switch() case would be better in this case, I just don't remember the syntax now
我认为在这种情况下使用 switch() case 会更好,我现在不记得语法了
Keep it Simple :)
把事情简单化 :)
回答by Robert Eisele
If it's possible to generate the pagination on the client, I would suggest my new Pagination plugin: http://www.xarg.org/2011/09/jquery-pagination-revised/
如果可以在客户端生成分页,我会建议我的新分页插件:http: //www.xarg.org/2011/09/jquery-pagination-revised/
The solution to your question would be:
您的问题的解决方案是:
$("#pagination").paging(1000, { // Your number of elements
format: '. - nncnn - ', // Format to get Pages: ... 3 4 [5] 6 7 ...
onSelect: function (page) {
// add code which gets executed when user selects a page
},
onFormat: function (type) {
switch (type) {
case 'block': // n and c
return '<a>' + this.value + '</a>';
case 'fill': // -
return '...';
case 'leap': // .
return 'Pages:';
}
}
});
回答by Natrium
The code of the CodeIgniter pagination-class can be found on GitHub
CodeIgniter 分页类的代码可以在 GitHub 上找到
(what you call) Smart pagination can be achieved by configuration.
(你所说的)智能分页可以通过配置来实现。
$config['num_links'] = 2;
The number of "digit" links you would like before and after the selected page number. For example, the number 2 will place two digits on either side, as in the example links at the very top of this page.
您希望在所选页码前后的“数字”链接数。例如,数字 2 将在任一侧放置两位数字,如本页最顶部的示例链接所示。

