msgbartop
PHP应用,PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享 – 左手代码 右手诗
msgbarbottom

28 Oct 08 一个巧妙的分页方法

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 = "&lt", $next_str = "&gt";
        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);
        }
}

Related Posts:

Tags: , , ,

21 Responses to “一个巧妙的分页方法”

Pages: [3] 2 1 » Show All

  1. MoontoC |

    看第一句我就真经了,虽然还算实用,但是得到的东西是不是自己想要的还待考证
    $total_page = ceil($total/$page_size);

    ceil之类的普通数学函数属于很不严谨的一类做法,它们可以出现任何意想不到的问题,源于php的浮点精度差别,php文档下面的评论可以看到一些神奇的东西…

    我想说的是,数据的格式化不足

Pages: [3] 2 1 » Show All

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word