zoukankan      html  css  js  c++  java
  • CI框架源码解析十九之分页类文件Pagination.php

         CodeIgniter 的分页类非常容易使用,而且它 100% 可定制,可以通过动态的参数,也可以通过保存在配置文件中的参数。如果你还不熟悉 "分页" 这个词,它指的是用于你在页面之间进行导航的链接。像下面这样:

    « First  < 1 2 3 4 5 >  Last »

    举个例子说明如何在你的控制器方法中创建分页:

    Ⅰ 在构造函数中引入分页类:

    [php] view plain copy
     
    1. public function __construct(){  
    2.     parent::__construct();  
    3.     $this->load->library('form_validation');  
    4.     $this->load->model('goodstype_model');  
    5.     $this->load->library('pagination');//引入分页类  
    6. }  

    Ⅱ 设置配置参数,然后初始化调用输出:

    [php] view plain copy
     
    1. public function index($offset = '')  
    2. {  
    3.     //配置分页信息  
    4.     $config['base_url'] = site_url('admin/goodstype/index');  
    5.     //获取数据库总条数  
    6.     $config['total_rows'] = $this->goodstype_model->count_goodstype();  
    7.     //每页显示条数  
    8.     $config['per_page'] = 2;  
    9.     //页码参数位置  
    10.     $config['uri_segment'] = 4;  
    11.   
    12.     //自定义分页连接  
    13.     $config['first_link'] = '首页';  
    14.     $config['last_link'] = '尾页';  
    15.     $config['prev_link'] = '上一页';  
    16.     $config['next_link'] = '下一页';  
    17.   
    18.     //初始化分类页  
    19.     $this->pagination->initialize($config);  
    20.     //生成分页信息  
    21.     //可以输出查看结果是一串html字符串  
    22.     $data['pageinfo'] = $this->pagination->create_links();  
    23.     $limit = $config['per_page'];  
    24.     $data['goodstypes'] = $this->goodstype_model->list_goodstype($limit,$offset);  
    25.     $this->load->view('goods_type_list.html',$data);  
    26. }  

            CI框架的分页类非常的好用,可以让我们随心所欲的去修改定制。但是在这里要说的是,CI框架的分页功能仅仅只是提供一个显示功能,不存在任何和数据库进行交互的作用,它所显示的仅仅只是一个连接,其具体的数据查询功能,数据显示功能还是要我们自己在模型中进行编写,这是CI框架的分页类和其他框架所不同的地方。大家要注意。好了,本篇就说这么多,其实分页类的代码功能还是非常简单明了的,只要稍微的看一篇就能明白其具体的实现过程。

            最后贴一下CI框架整个分页类Pagination.php文件的源代码(注释版):

    [php] view plain copy
     
    1. <?php  
    2.   
    3. /** 
    4.  * ======================================= 
    5.  * Created by Pocket Knife Technology. 
    6.  * User: ZhiHua_W 
    7.  * Date: 2016/11/08 0041 
    8.  * Time: 下午 4:14 
    9.  * Project: CodeIgniter框架—源码分析 
    10.  * Power: Analysis for Pagination.php 
    11.  * ======================================= 
    12.  */  
    13.   
    14. defined('BASEPATH') OR exit('No direct script access allowed');  
    15.   
    16. /** 
    17.  * 用于生成分页连接 
    18.  */  
    19. class CI_Pagination  
    20. {  
    21.     //每次访问的url地址  
    22.     protected $base_url = '';  
    23.     //给路径添加一个自定义前缀,前缀位于偏移段的前面  
    24.     protected $prefix = '';  
    25.     //给路径添加一个自定义后缀,后缀位于偏移段的后面。  
    26.     protected $suffix = '';  
    27.     //这个数字表示你需要做分页的数据的总行数。通常这个数值是你查询数据库得到的数据总量。  
    28.     protected $total_rows = 0;  
    29.     //放在你当前页码的前面和后面的“数字”链接的数量。  
    30.     //比方说值为 2 就会在每一边放置两个数字链接,就像此页顶端的示例链接那样。  
    31.     protected $num_links = 2;  
    32.     //这个数字表示每个页面中希望展示的数量,在上面的那个例子中,每页显示 10 个项目。  
    33.     public $per_page = 10;  
    34.     //当前页  
    35.     public $cur_page = 0;  
    36.     //默认分页的 URL 中显示的是你当前正在从哪条记录开始分页,  
    37.     //如果你希望显示实际的页数,将该参数设置为 TRUE 。  
    38.     protected $use_page_numbers = FALSE;  
    39.     //首页,左边第一个链接显示的文本,如果你不想显示该链接,将其设置为 FALSE 。  
    40.     protected $first_link = '‹ First';  
    41.     //下一页,下一页链接显示的文本,如果你不想显示该链接,将其设置为 FALSE 。  
    42.     protected $next_link = FALSE;  
    43.     //下一页,下一页链接显示的文本,如果你不想显示该链接,将其设置为 FALSE  
    44.     protected $prev_link = FALSE;  
    45.     //尾页,右边第一个链接显示的文本,如果你不想显示该链接,将其设置为 FALSE 。  
    46.     protected $last_link = 'Last ›';  
    47.     //分页方法自动检测你 URI 的哪一段包含页数,如果你的情况不一样,你可以明确指定它  
    48.     protected $uri_segment = 4;  
    49.     //起始标签放在所有结果的左侧。  
    50.     //你可以在标签里面写任意的样式等等  
    51.     //不过样式最好的还是采取分离的方式写最好,仅在这边添加不同的class就可以了  
    52.     protected $full_tag_open = '<ul class="pagination pagination-sm">';  
    53.     //结束标签放在所有结果的右侧。  
    54.     protected $full_tag_close = '</ul>';  
    55.     //第一个链接的起始标签。  
    56.     protected $first_tag_open = '<li>';  
    57.     //第一个链接的结束标签。  
    58.     protected $first_tag_close = '</li>';  
    59.     //最后一个链接的起始标签。  
    60.     protected $last_tag_open = '<li>';  
    61.     //最后一个链接的结束标签。  
    62.     protected $last_tag_close = '</li>';  
    63.     //首页url  
    64.     protected $first_url = '';  
    65.     //当前页链接的起始标签。  
    66.     protected $cur_tag_open = '<li class="active"><a href="javascript:;">';  
    67.     //当前页链接的结束标签。  
    68.     protected $cur_tag_close = '</a></li>';  
    69.     //下一页链接的起始标签。  
    70.     protected $next_tag_open = '<li>';  
    71.     //下一页链接的结束标签。  
    72.     protected $next_tag_close = '</li>';  
    73.     //上一页链接的起始标签。  
    74.     protected $prev_tag_open = '<li>';  
    75.     //上一页链接的结束标签。  
    76.     protected $prev_tag_close = '</li>';  
    77.     //数字链接的起始标签。  
    78.     protected $num_tag_open = '<li>';  
    79.     //数字链接的结束标签。  
    80.     protected $num_tag_close = '</li>';  
    81.     //默认情况下,分页类假设你使用 URI 段 ,并像这样构造你的链接:  
    82.     //http://example.com/index.php/test/page/20  
    83.     protected $page_query_string = FALSE;  
    84.     protected $query_string_segment = 'per_page';  
    85.     //如果你不想显示数字链接(例如你只想显示上一页和下一页链接),你可以将下面的代码TRUE改为FALSE来阻止它显示  
    86.     protected $display_pages = TRUE;  
    87.     //如果你想为分页类生成的每个链接添加额外的属性  
    88.     protected $_attributes = '';  
    89.     //连接类型  
    90.     protected $_link_types = array();  
    91.     //默认情况下你的查询字符串参数会被忽略,将这个参数设置为 TRUE ,  
    92.     //将会将查询字符串参数添加到 URI 分段的后面以及 URL 后缀的前面  
    93.     protected $reuse_query_string = FALSE;  
    94.     //当该参数设置为 TRUE 时,会使用 application/config/config.php  
    95.     //配置文件中定义的 $config['url_suffix'] 参数 重写 $config['suffix'] 的值  
    96.     protected $use_global_url_suffix = FALSE;  
    97.     //给数字增加属性  
    98.     protected $data_page_attr = 'data-ci-pagination-page';  
    99.     //CI Singleton  
    100.     protected $CI;  
    101.   
    102.     /** 
    103.      * 构造函数->处理数据 
    104.      * 在使用加载此类之后,设置一些数据例如: 
    105.      * //配置分页信息 
    106.      * $config['base_url'] = site_url('admin/goodstype/index'); 
    107.      * $config['total_rows'] = $this->goodstype_model->count_goodstype(); 
    108.      * $config['per_page'] = 2; 
    109.      * $config['uri_segment'] = 4; 
    110.      * 
    111.      * //自定义分页连接 
    112.      * $config['first_link'] = '首页'; 
    113.      * $config['last_link'] = '尾页'; 
    114.      * $config['prev_link'] = '上一页'; 
    115.      * $config['next_link'] = '下一页'; 
    116.      */  
    117.     public function __construct($params = array())  
    118.     {  
    119.         $this->CI = &get_instance();  
    120.         $this->CI->load->language('pagination');  
    121.         foreach (array('first_link', 'next_link', 'prev_link', 'last_link') as $key) {  
    122.             if (($val = $this->CI->lang->line('pagination_' . $key)) !== FALSE) {  
    123.                 $this->$key = $val;  
    124.             }  
    125.         }  
    126.         $this->initialize($params);  
    127.         log_message('info', 'Pagination Class Initialized');  
    128.     }  
    129.   
    130.     /** 
    131.      * 初始化 
    132.      * 功能同样是处理参数 
    133.      */  
    134.     public function initialize(array $params = array())  
    135.     {  
    136.         isset($params['attributes']) OR $params['attributes'] = array();  
    137.         if (is_array($params['attributes'])) {  
    138.             $this->_parse_attributes($params['attributes']);  
    139.             unset($params['attributes']);  
    140.         }  
    141.   
    142.         if (isset($params['anchor_class'])) {  
    143.             empty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class'];  
    144.             unset($params['anchor_class']);  
    145.         }  
    146.   
    147.         foreach ($params as $key => $val) {  
    148.             if (property_exists($this, $key)) {  
    149.                 $this->$key = $val;  
    150.             }  
    151.         }  
    152.   
    153.         if ($this->CI->config->item('enable_query_strings') === TRUE) {  
    154.             $this->page_query_string = TRUE;  
    155.         }  
    156.   
    157.         if ($this->use_global_url_suffix === TRUE) {  
    158.             $this->suffix = $this->CI->config->item('url_suffix');  
    159.         }  
    160.   
    161.         return $this;  
    162.     }  
    163.   
    164.     /** 
    165.      * 创建分页连接 
    166.      * 这个就是我们需要条用到的了,这个函数最后会返回一串html代码, 
    167.      * 而我们仅将这段html代码在前台显示即可。 
    168.      * CI框架的分页类和TP框架的分页类有这明显的差别。 
    169.      * CI仅是提供分页显示,并不提供其和数据库交互的功能。 
    170.      * 这也就让我们可以对其进行100%的定制。 
    171.      * 非常的小巧方便。 
    172.      */  
    173.     public function create_links()  
    174.     {  
    175.         //我们在初始化的时候必须要有数据总条数和每页显示条数  
    176.         if ($this->total_rows == 0 OR $this->per_page == 0) {  
    177.             return '';  
    178.         }  
    179.         //计算页面总数  
    180.         $num_pages = (int)ceil($this->total_rows / $this->per_page);  
    181.         //如果只有一页,则直接然会空字符串  
    182.         if ($num_pages === 1) {  
    183.             return '';  
    184.         }  
    185.         //检查用户定义的链接数  
    186.         $this->num_links = (int)$this->num_links;  
    187.         if ($this->num_links < 0) {  
    188.             show_error('Your number of links must be a non-negative number.');  
    189.         }  
    190.   
    191.         //保留任何现有的查询字符串项目。  
    192.         //注:与任何其他查询字符串选项无关。  
    193.         if ($this->reuse_query_string === TRUE) {  
    194.             $get = $this->CI->input->get();  
    195.             unset($get['c'], $get['m'], $get[$this->query_string_segment]);  
    196.         } else {  
    197.             $get = array();  
    198.         }  
    199.   
    200.         //处理我们的基础网址和第一个网址  
    201.         $base_url = trim($this->base_url);  
    202.         $first_url = $this->first_url;  
    203.         $query_string = '';  
    204.         $query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&';  
    205.         if ($this->page_query_string === TRUE) {  
    206.             //如果自定义first_url还没有被确定,我们会从base_url创建一个网页,但没有项目。  
    207.             if ($first_url === '') {  
    208.                 $first_url = $base_url;  
    209.                 if (!empty($get)) {  
    210.                     $first_url .= $query_string_sep . http_build_query($get);  
    211.                 }  
    212.             }  
    213.             $base_url .= $query_string_sep . http_build_query(array_merge($get, array($this->query_string_segment => '')));  
    214.         } else {  
    215.             //生成我们保存的查询字符串,以在页面号以后追加。  
    216.             if (!empty($get)) {  
    217.                 $query_string = $query_string_sep . http_build_query($get);  
    218.                 $this->suffix .= $query_string;  
    219.             }  
    220.             if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE) {  
    221.                 $base_url = substr($base_url, 0, $base_query_pos);  
    222.             }  
    223.             if ($first_url === '') {  
    224.                 $first_url = $base_url . $query_string;  
    225.             }  
    226.   
    227.             $base_url = rtrim($base_url, '/') . '/';  
    228.         }  
    229.   
    230.         //确定当前页号。  
    231.         $base_page = ($this->use_page_numbers) ? 1 : 0;  
    232.         //判断我们是否使用查询字符串  
    233.         if ($this->page_query_string === TRUE) {  
    234.             $this->cur_page = $this->CI->input->get($this->query_string_segment);  
    235.         } elseif (empty($this->cur_page)) {  
    236.             //如果uri_segment一个没有被定义,默认的最后一个段的数字。  
    237.             if ($this->uri_segment === 0) {  
    238.                 $this->uri_segment = count($this->CI->uri->segment_array());  
    239.             }  
    240.             $this->cur_page = $this->CI->uri->segment($this->uri_segment);  
    241.             //从该段中删除任何指定的前缀/后缀。  
    242.             if ($this->prefix !== '' OR $this->suffix !== '') {  
    243.                 $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);  
    244.             }  
    245.         } else {  
    246.             $this->cur_page = (string)$this->cur_page;  
    247.         }  
    248.         if (!ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int)$this->cur_page === 0)) {  
    249.             $this->cur_page = $base_page;  
    250.         } else {  
    251.             //确保我们使用的是比较后的整数。  
    252.             $this->cur_page = (int)$this->cur_page;  
    253.         }  
    254.         if ($this->use_page_numbers) {  
    255.             if ($this->cur_page > $num_pages) {  
    256.                 $this->cur_page = $num_pages;  
    257.             }  
    258.         } elseif ($this->cur_page > $this->total_rows) {  
    259.             $this->cur_page = ($num_pages - 1) * $this->per_page;  
    260.         }  
    261.   
    262.         $uri_page_number = $this->cur_page;  
    263.         //如果我们使用的是偏移量而不是页面号,将它转换为一个页面号,  
    264.         //这样我们就可以生成周围的数字链接了。  
    265.         if (!$this->use_page_numbers) {  
    266.             $this->cur_page = (int)floor(($this->cur_page / $this->per_page) + 1);  
    267.         }  
    268.   
    269.         //计算开始和结束的数字。这些决定开始和结束数字链接的数量。  
    270.         $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;  
    271.         $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;  
    272.   
    273.         //这个变量就是最后返回的字符串  
    274.         $output = '';  
    275.   
    276.         //生成首页链接  
    277.         if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1 + !$this->num_links)) {  
    278.             //为html代码添加设置的js属性  
    279.             $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);  
    280.             $output .= $this->first_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>' . $this->first_link . '</a>' . $this->first_tag_close;  
    281.         }  
    282.   
    283.         // 生成上一页链接  
    284.         //我个人感觉生成上一页的这个连接没用,我们本身已经有了和相邻的页面连接  
    285.         //故而上一页和下一页在我看来没有用处,我一般都是将此段和下一页都注视掉  
    286.         if ($this->prev_link !== FALSE && $this->cur_page !== 1) {  
    287.             $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;  
    288.             $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));  
    289.             if ($i === $base_page) {  
    290.                 $output .= $this->prev_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('prev') . '>' . $this->prev_link . '</a>' . $this->prev_tag_close;  
    291.             } else {  
    292.                 $append = $this->prefix . $i . $this->suffix;  
    293.                 $output .= $this->prev_tag_open . '<a href="' . $base_url . $append . '"' . $attributes . $this->_attr_rel('prev') . '>' . $this->prev_link . '</a>' . $this->prev_tag_close;  
    294.             }  
    295.         }  
    296.         //渲染页面  
    297.         //也就是将你设置的所需要添加的html标签代码,属性,都给加上  
    298.         if ($this->display_pages !== FALSE) {  
    299.             for ($loop = $start - 1; $loop <= $end; $loop++) {  
    300.                 $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;  
    301.                 $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop);  
    302.                 if ($i >= $base_page) {  
    303.                     if ($this->cur_page === $loop) {  
    304.                         $output .= $this->cur_tag_open . $loop . $this->cur_tag_close;  
    305.                     } elseif ($i === $base_page) {  
    306.                         $output .= $this->num_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>' . $loop . '</a>' . $this->num_tag_close;  
    307.                     } else {  
    308.                         $append = $this->prefix . $i . $this->suffix;  
    309.                         $output .= $this->num_tag_open . '<a href="' . $base_url . $append . '"' . $attributes . '>' . $loop . '</a>' . $this->num_tag_close;  
    310.                     }  
    311.                 }  
    312.             }  
    313.         }  
    314.         //生成下一页连接  
    315.         //不多说  
    316.         if ($this->next_link !== FALSE && $this->cur_page < $num_pages) {  
    317.             $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;  
    318.             $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);  
    319.             $output .= $this->next_tag_open . '<a href="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes . $this->_attr_rel('next') . '>' . $this->next_link . '</a>' . $this->next_tag_close;  
    320.         }  
    321.         //生成最后一页(尾页)连接  
    322.         if ($this->last_link !== FALSE && ($this->cur_page + $this->num_links + !$this->num_links) < $num_pages) {  
    323.             $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;  
    324.             $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);  
    325.             $output .= $this->last_tag_open . '<a href="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes . '>' . $this->last_link . '</a>' . $this->last_tag_close;  
    326.         }  
    327.         //将生成的结果html代码字符串进行处理  
    328.         $output = preg_replace('#([^:"])//+#', '\1/', $output);  
    329.         //如果存在添加封装HTML  
    330.         return $this->full_tag_open . $output . $this->full_tag_close;  
    331.     }  
    332.   
    333.     /** 
    334.      * 解析属性 
    335.      */  
    336.     protected function _parse_attributes($attributes)  
    337.     {  
    338.         isset($attributes['rel']) OR $attributes['rel'] = TRUE;  
    339.         $this->_link_types = ($attributes['rel']) ? array('start' => 'start', 'prev' => 'prev', 'next' => 'next') : array();  
    340.         unset($attributes['rel']);  
    341.         $this->_attributes = '';  
    342.         foreach ($attributes as $key => $value) {  
    343.             $this->_attributes .= ' ' . $key . '="' . $value . '"';  
    344.         }  
    345.     }  
    346.   
    347.     /** 
    348.      * 添加“关系”属性 
    349.      */  
    350.     protected function _attr_rel($type)  
    351.     {  
    352.         if (isset($this->_link_types[$type])) {  
    353.             unset($this->_link_types[$type]);  
    354.             return ' rel="' . $type . '"';  
    355.         }  
    356.         return '';  
    357.     }  
    358.   
    359. }  

    注:其中有部分代码标签是我自己添加的,其变量表示和源码有点不一样,大家看的时候要注意!后面再写这些博文,一般就没有什么规律的,一般都是用到那个酒吧那个写一遍。

  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/zhq--blog/p/7561373.html
Copyright © 2011-2022 走看看