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

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

posted @ 2017-09-20 14:37  菊丸太  阅读(321)  评论(0编辑  收藏  举报