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. }  

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

  • 相关阅读:
    关于 SAP UI5 对服务器端渲染 Server Sider Render 的支持问题
    java基础_数组_数据类型_原码反码补码_进制转换_编码_shell
    java基础_==与equals,try catch finally return ,装箱与拆箱, 字符串
    Java基础_泛型详解
    java基础_吃透Java集合系列九:HashMap
    java基础_吃透Java集合
    java基础_TCP和UDP总结及常见面试题
    java基础_由i++引发的并发问题_volatile关键词详析
    SpringBoot:SpringBoot项目的配置文件放在Jar包外加载和jar包打成exe
    对docker拉取镜像的一个知识点弥补不足
  • 原文地址:https://www.cnblogs.com/zhq--blog/p/7561373.html
Copyright © 2011-2022 走看看