- 本文地址: https://www.laruence.com/2008/10/28/567.html
- 转载请注明出处
PHP是一个Web脚本语言,在Web应用中最常见的莫过于列表显示。所以页码生成也就犹为常用。 最近我索性写了一个,在生成思想上, 有一些技巧拿与大家分享:
先说说需求: 显示的页码数是$size, 当前的页数是$page, 总数是$total, 每页显示的条数是$page_size
首先,要获取总页面数是多少:
$total_page = ceil($total/$page_size);
这样的写法是不是更简单一些呢?
其次,我是这样想的, 这个需求最高的需求是要根据当前的页码,找出size个页码数来。
那么就可以转化为: 根据当前的信息, 填充一个size个元素的数组。
最终就可以简单的转化为:根据当前的信息,寻找出size个元素的数组的起始元素是什么?我们假设这个起始元素是:page_start;
$page_start = 1; $half = intval($size/2); $page_start = max(1, $page - $half); $page_end = min($page_start + $size - 1, $total_page); $page_start = max(1, $page_end - $size + 1);
这样写,是不是也很有技巧呢?
最后就简单了, 根据起始页和结束页, 生成一个数组, 最后foreach这个数组,生成html代码:
$page_numbers = range($page_start, $page_end); $nav_str = ""; foreach($page_numbers as $num){ //....... }
源码:
/** *A pagination generation class *@class : Pagination *@version: 1.0.0 *@author : huixinchen at baidu.com *@useage: * $pagi = new Pagination($url_prefix, $page_size, $mesgs_count, $pagination_size=10, array $conf); * $navigation_str = $pagi->generate($current_page_number); */ class Pagination{ private $page, $total_page, $total, $page_size, $size; private $prev_str = "<", $next_str = ">"; private $class, $selected_class = "selected", $prev_class="prev", $next_class="next", $de_prev_class="de_prev", $de_next_class="de_next"; private $url_prefix="", $split_char="?"; private $para_name = "page", $target = ""; public function Pagination($url_prefix, $page_size, $total, $size=10, $conf=array()){ $this->page = 1; $this->page_size = $page_size; $this->total = $total; $this->total_page = intval(ceil($total/$page_size)); $this->size = $size; if(!empty($conf)){ $configure = array("prev_str", "next_str", "class", "selected_class"); foreach($conf as $key => $val){ if(in_array($key, $configure)){ $this->$val = $val; } } } $this->url_prefix = $url_prefix; if(strstr($url_prefix, '?') !== false){ $this->url_prefix .= "&" . $this->para_name . "="; }else{ $this->url_prefix .= "?" . $this->para_name . "="; } } public function generate($page){ $this->page = $page; if(isset($this->page[$page])){ return $this->page_str[$page]; } $page_start = 1; $half = intval($this->size/2); $page_start = max(1, $page - $half); $page_end = min($page_start + $this->size - 1, $this->total_page); $page_start = max(1, $page_end - $this->size + 1); $this->page_str[$page] = $this->build_nav_str($page_start, $page_end); return $this->page_str[$page]; } private function build_nav_str($page_start, $page_end){ $page_nums = range($page_start, $page_end); $target = $this->target? " target=\"{$this->target}\"" : ""; if($this->page == 1){ $page_str = <<<html <span class="{$this->de_prev_class}"> {$this->prev_str} </span> HTML; }else{ $page = $this->page - 1; $page_str = <<<html <span class="{$this->prev_class}"> <a href="{$this->url_prefix}{$page}"{$this->target}>{$this->prev_str}</a></span> HTML; } foreach($page_nums as $p){ $page_str .= ($p == $this->page) ? <<<html <span class="{$this->selected_class}">{$p}</span> HTML : <<<html <span class="{$this->class}"><a href="{$this->url_prefix}{$p}"{$this->target}>{$p}</a></span> HTML; } if($this->page == $this->total_page){ $page_str .= <<<html <span class="{$this->de_next_class}"> {$this->next_str} </span> HTML; }else{ $page = $this->page + 1; $page_str .= <<<html <span class="{$this->next_class}"> <a href="{$this->url_prefix}{$page}"{$this->target}>{$this->next_str}</a></span> HTML; } return $page_str; } public function tidy_str(){ ;//void } public function __call($func_name, $arguments){ if(isset($this->$func_name)){ return $this->$func_name; } } public function __destruct(){ unset($this->page_str); unset($this); } }
测试测试
Admiring the time and effort you put into your blog and
in depth information you offer. It’s nice to come across a blog
every once in a while that isn’t the same outdated rehashed
information. Great read! I’ve bookmarked your site and
I’m adding your RSS feeds to my Google account.
还有这句是不是也写错了?
if(isset($this->page[$page])){
return $this->page_str[$page];
}
应该是if(isset($this->page_str[$page]))这样的吧?
弱弱的问一句,这段代码里if里面的语句是不是写错了啊?
$configure = array(“prev_str”, “next_str”, “class”, “selected_class”);
foreach($conf as $key => $val){
if(in_array($key, $configure)){
$this->$val = $val;
}
}
难道不是 $this->$key = $val;么?
这个我以前也写过,现在看到完全熟悉的思路和陌生的变量名,感觉很奇妙呢。有些朋友对以下5行代码不是很明白,我帮忙解释一下吧
$page_start = 1;
$half = intval($size/2);/*获取显示页码数的一半,必须整*/
$page_start = max(1, $page – $half);/*起始页码,不能小于1*/
$page_end = min($page_start + $size – 1, $total_page);/*确定结束页码,不能大于最大页*/
$page_start = max(1, $page_end – $size + 1);/*这是精华,若$size=10;$total_page=50;$page=49; 可避免显示44~50,而是更友好的显示41~50*/
这一段:
$page_start = 1;
$half = intval($size/2);
$page_start = max(1, $page – $half);
$page_end = min($page_start + $size – 1, $total_page);
$page_start = max(1, $page_end – $size + 1);
第五行不理解。。
为什么需要再次计算$page_start呢?
如果去掉第五行有什么问题呢?
谢谢
可能是我比较笨吧,这5行代码,看了好几个小时没看懂。
$page和$size有区别吗?如果都是代表当前页为什么要取2个变量呢?
还有$half的这个值为什么要取一半呢?
$page_start = 1;
$half = intval($size/2);
$page_start = max(1, $page – $half);
$page_end = min($page_start + $size – 1, $total_page);
$page_start = max(1, $page_end – $size + 1);
你这5行代码能讲讲是用了什么思想呢。
鸟哥~~
$page_str .= <<<HTML
de_next_class}”> {$this->next_str}
HTML;
您这样写是因为效率还是为了整洁啊?
这个好处是什么?
[…] 出处: http://www.laruence.com/2008/10/28/567.html […]
[…] 本文地址: http://www.laruence.com/2008/10/28/567.html […]
看第一句我就真经了,虽然还算实用,但是得到的东西是不是自己想要的还待考证
$total_page = ceil($total/$page_size);
ceil之类的普通数学函数属于很不严谨的一类做法,它们可以出现任何意想不到的问题,源于php的浮点精度差别,php文档下面的评论可以看到一些神奇的东西…
我想说的是,数据的格式化不足
如果想写一个功能强大的分页类,那我建议写一个分页方面的框架吧,可以分为以下几个方面:
1、主类:用来实现分页
2、数据生成类:用来生成数据
3、现实效果类:用来现实分页的效果,这个类支持插件,自己可以随便自定义现实效果
4、插件类:用于其他一些功能
当然可能还会有其他的一些分法和功能
最重要的还是设计模式的良好运用
哎~这两天什么也没做,就研究你博客了。呵呵~~刚看了这篇,在找出$size个页码时我见过这种方法:
$half = ceil($size/2);
if($size-$half+$page > $total) {
$half = $size-$total+$page;
}
$begin = $page – $half + 1;
$begin = ($begin>=1)? $begin : 1;
for($i=$begin;$i<$begin+$size;$i++) {
if($i<=$total) {
….
}
}
哎,本人才疏学浅,对于上面的和这个的思想都不是太了解,还请您指点~~不胜感激~
自己也写了一个,没这么复杂,传入
$totalNum = $arr[‘totalNum’];
$numPerPage = $arr[‘numPerPage’];
$nowPage = $arr[‘nowPage’];
$href = $arr[‘href’];
这4个参数,自己返回分页的link。就43行代码
太复杂了,呵呵
速度啊,大哥,要下班了,给我说两下吧,今天看你的那个类都一天了,还是没有看明白,555
我觉得你要关心的是这个思想, 不用太在意这个类。
作者的本意,也只是一个思想么。
开始传参数时,$conf=array(),这个值开始时传什么呢? 还有就是,点击1,2,3,4,5的链接是,如何把值传传出去的呢?你的{$this->target}没法传值啊
恩,这个conf是我留下做特殊定制的,一般不需要.
很多变量看不懂什么含义,一个方法这么多变量,不是很难用麽?还忘作者能吧各个变量什么意思,说明白。
hi, 变量名的命名都是根据变量的实际意义来的,应该不难理解,;)
大哥啊,你在线?能否给我说说 变量的意义,我看懂了类80%的东西,还差点就能用了 我QQ:492902285 方便聊下麽?
感觉只用做成render的一个插件函数就搞定, 这样调用过于麻烦
虽然我也大都不能理解这些文字,但我还是要来的...(决不是有意给本blog抹黑)
呵呵,good boy.
学习了
我的想法是这样的,把页码生成的单独包一下(Core),把样式化页码的东东(涉及HTML的)写成一个包装器(Decoration),每次要用的时候包装下(eg.$page=new PageDecoration(new PageCore(args[0],args[1]…))),我觉得这样还蛮方便,算是逻辑与显示小分离了下,不知道搂主怎么看
我觉得写一个分页类不难,但是要写一个可扩展性及自定义功能极强的分页类就不容易了,至今还没找到非常好用的分页类。
之前一直都是用别人写好的一个分页类, 在不同的项目中,产品人员总是会对分页效果提出各种各样的需求,所以每次都得把这个分页类
拷贝一份,然后修改其中的HTML,修改样式,甚至修改和添加新的逻辑.总之觉得挺麻烦的,当然在类中可以把这些设计成可配置项,也可以
用switch来根据参数进行不同类型的输出.总之感觉不能一处开发,多场合使用.我觉得好的分页类不应该只是一个类而已,应该还可以拆卸,,
逻辑和表现都能分离到不同的层中,在表现层用多态,可以根据不同的场合自定义表现层的类.希望有这样的分页类,自己懒的写.
恩,你说的很对。
我这个其实主要还是介绍解决这样问题的一个方法
最后的类,也只是我现在用的一个包装。 呵呵
没必要什么扩展什么的,规范个格式,输入是$nowPage,$totalPage.
输出就是一个有10个数字点击的分页。。
老外有一个用策略模式做的分页:
http://www.sitepoint.com/article/perfect-php-pagination/
我觉得,把关键的分界输出(最后一页,当前页,其他都是扩展参数,比如上一页,下一页,上n页下n页),至于显示,交给smarty去做即可,甚至完全写成smarty的插件也行,在插件内部用smarty fetch动态获取分页模板