PHP分页类, 仿StackOverflow


看到StackOverflow的分页栏, 觉得很不错, 所以尝试用PHP来实现. 我以为可以很容易实现的, 结果一动手写才发现, 这么一个分页功能实现起来一点也不简单, 因为有很多临界的情况要考虑, 程序必须在各种参数下都可以正常工作. 不断的修改, 用不同的参数测试, 改了好一阵, 结果还是用了50多行代码. 可能过个几天, 自己再来看也看不懂, 不过正常工作是可以了.

<?php
class ZZ_Pager {
    public $page;
    public $count;
    public $pagesize 2;
    public $span 3;// >= 3 
    
    function init($page,$count) {
        $this->page = $page;
        $this->count = $count;
        
        
        // 20 2 -> 10
        // 21 2 -> 11
        $this->pagecount = ceil($count $this->pagesize);
        $this->page = $this->page < $this->page;
        $this->page = $this->page > $this->pagecount ? $this->pagecount : $this->page;

        $this->start = ($this->page - 1) * $this->pagesize;

        
    }
    
    function getStart() {
        return $this->start;
    }

    function outPagebar($filter) {

        //StackOverflow的就很不错 , span是5
        // 1. prev 2. head 3.[...] 4. xxPxx 5[...] 6.end 7.next
        // 7个步骤可以生成列表
        if($this->page > 1) {
            $this->outLink($this->page -,'前一页',"转到第".($this->page - 1)."页",'pre');
        }
        
        if($this->page != 1$this->outLink(1,'1');
        else $this->outCurrent(1);
        
        $spanhalf = ($this->span - 1) / 2;
        $startdot $spanhalf;
        $lastouted false;
        $spanend;
        if($this->page >= $startdot) {
            
            $offset $this->page + $spanhalf $this->pagecount ? $this->page + $spanhalf $this->pagecount : 0;
            if($offset == && $this->page + $spanhalf == $this->pagecount) $offset--;
            if(($this->page - $spanhalf $offset) > 2)
                echo '<span    class="page-number" style="border:1px solid white;">...</span>';
            $i 0;
            for($i $this->page - $spanhalf $offset  $i <= $this->page + $spanhalf && $i <= $this->pagecount ; $i++)
            {
                if($i == 1continue;
                if($i == $this->pagecount) $lastouted true;
                if($i == $this->page) 
                    $this->outCurrent($i);
                else 
                    $this->outLink($i,$i);
            }
            $spanend $i;
        }
        else {
            //从2到page,然后page, 然后page + 1 page +2
            $i 0;
            for($i $i <= $this->span && $i <= $this->pagecount; $i++) {
                if($i == $this->pagecount) $lastouted true;
                if($i == $this->page) 
                    $this->outCurrent($i);
                else 
                    $this->outLink($i,$i);
            }
            $spanend $i;
        }
        
        // 当小于某个值的时候,要显示后面的那个dot
        $enddot $this->pagecount - $spanhalf;
        $spanend--;
        if($spanend < ($this->pagecount - 1))
            echo '<span    class="page-number" style="border:1px solid white;">...</span>';
        
        if(!$lastouted) {
            if($this->page != $this->pagecount) 
                $this->outLink($this->pagecount,$this->pagecount);
            else
                $this->outCurrent($this->pagecount);
        }        
        
        if($this->page != $this->pagecount) 
            $this->outLink($this->page + ,'后一页',"转到第".($this->page + 1)."页",'pre');
    }
    
    function outLink($page,$text,$alt "",$class "") {
        ?>
            <a class="page-item " href="/?page=<?=$page?>title="转到第<?php echo $page?>页">
                <span class="page-number <?=$class?>"><?=$text?></span>
            </a>
        <?php
    }
    
    function outCurrent($page) {
        ?>
        <span class="page-number currentpage"><?=$page?></span>
        <?php
    }
}
?>

初始化需要两个参数, 一个是当前的页, 一个是总的记录数. 该类提供两个功能, 一个是向执行sql查询的代码提供limit语句中的start参数, 一个是输出分页栏的HTML代码. 其中filter参数应该是排序依据的URL参数, 这个由调用者提供, Pager类负责生成page参数.

span应该是一个奇数, 从3开始.

下图是记录数为9时候的情况: