自定义 WordPress 插件如何对记录进行分页

在我们为 WordPress 开发插件的时候,在涉及到列表显示许多记录的时候,肯定要考虑分页显示的问题。自然的,不管是简单性也好,还是统一性,直接参考下 WordPress 自己是怎么实现的,看看 Posts 或 User 管理页面的实现代码,比如 User 管理页面的实现代码在 wp-admin/includes/user.php 中的 WP_User_Search 类。默认实现其实是很好看的,如:。那我们如何在自己的插件里实现这样的效果呢,比如像这个:



我的做法是新建了自己的一个 Pagination 类,My_Pagination 类的内容如下:
  1<?php
  2/**
  3 * Used for show paged records
  4 * @author Unmi
  5 */
  6class FN_Pagination {
  7
  8    /**
  9     * data to display
 10     */
 11    var $results;
 12
 13    /**
 14     * Page number.
 15     * @var int
 16     */
 17    var $current_page_number;
 18
 19    /**
 20     * Amount of records to display per page.
 21     * @access public
 22     * @var int
 23     */
 24    var $records_per_page = 20;
 25
 26    /**
 27     * @var int
 28     */
 29    var $total_record_count = 1;
 30
 31    /**
 32     * @access private
 33     * @var string
 34     */
 35    var $paging_text;
 36
 37    /**
 38     * @var string
 39     */
 40    var $base_page_url;
 41
 42    /**
 43     * PHP4 Constructor - Sets up the object properties.
 44     * @param string $prepare_sql_str 一个不带 LIMIT 的 sql 语句
 45     * @param string $base_page_url 分页跳转时的 URL,用于生成分页的 URL
 46     * @param string $current_page_number 当前页号,从请求中可取得
 47     * @param int $records_per_page 每页记录数
 48     * @return FN_Pagination
 49     */
 50    function FN_Pagination ($prepare_sql_str,$base_page_url, $current_page_number = '',$records_per_page=20) {
 51        $this->base_page_url = $base_page_url;
 52        $this->current_page_number = (int) ( '' == $current_page_number ) ? 1 : $current_page_number;
 53        $this->records_per_page = $records_per_page;
 54        $this->query($prepare_sql_str);
 55        $this->do_paging();
 56    }
 57
 58    /**
 59     *
 60     * @access public
 61     */
 62    function query($prepare_sql_str) {
 63        global $wpdb;
 64
 65        $get_count_sql = preg_replace("/SELECT.+?FROM/is","SELECT count('c') FROM",$prepare_sql_str,1);
 66
 67        //if sql string contains group by
 68        if(preg_match("/group.+?by/is", $get_count_sql) >0 ) {
 69            //$this->total_record_count = count($wpdb->get_col($wpdb->prepare($get_count_sql)));
 70            $this->total_record_count = $wpdb->get_var(
 71                $wpdb->prepare("select count('c') from (($get_count_sql) as a)"));
 72        }else{
 73            $this->total_record_count = $wpdb->get_var($wpdb->prepare($get_count_sql));
 74        }
 75
 76        //or
 77        //$this->total_record_count = $wpdb->get_var(
 78        //  $wpdb->prepare("select count('c') from (($get_count_sql) as a)"));
 79
 80        $start_record = ($this->current_page_number-1) * $this->records_per_page;
 81        //此方面前面部分只是为了获得记录总数,分了带不带 group by 的情况
 82
 83        $this->results = $wpdb->get_results($wpdb->prepare($prepare_sql_str. " LIMIT $start_record,$this->records_per_page"));
 84    }
 85
 86    /**
 87     *
 88     * @since unknown
 89     * @access public
 90     */
 91    function do_paging() {
 92
 93        if ( $this->total_record_count > $this->records_per_page ) { // have to page the results
 94
 95            //调用了 wp-includes/general-template.php 中的 paginate_links() 方法用于产生用于页面显示的导航链接
 96            $this->paging_text = paginate_links( array(
 97                'total' => ceil($this->total_record_count / $this->records_per_page),
 98                'current' => $this->current_page_number,
 99                'base' => $this->base_page_url . '&amp;%_%',
100                'format' => 'page_no=%#%'
101            ) );
102
103            //理解一下用的占位符,通过 format 和 base,会生成像如下的链接,注意何时 ?%_%,何时&amp;%_%
104            // http://unmi/wp-admin/admin.php?page=my_plugin/tracking-logs.php&amp;page_no=2
105
106            if ( $this->paging_text ) {
107                $this->paging_text = sprintf( '<span class="displaying-num">' . __( 'Displaying %s–%s of %s' ) . '</span>%s',
108                    number_format_i18n( ( $this->current_page_number - 1 ) * $this->records_per_page + 1 ),
109                    number_format_i18n( min( $this->current_page_number * $this->records_per_page, $this->total_record_count ) ),
110                    number_format_i18n( $this->total_record_count ),
111                    $this->paging_text
112                );
113            }
114        }
115    }
116
117    /**
118     * @access public
119     */
120    function get_results() {
121        return (array) $this->results;
122    }
123
124    /**
125     * Displaying paging text.
126     * @access public
127     */
128    function page_links() {
129        echo $this->paging_text;
130    }
131
132    /**
133     * Whether paging is enabled.
134     * @see do_paging() Builds paging text.
135     * @access public
136     * @return bool
137     */
138    function results_are_paged() {
139        if ( $this->paging_text )
140            return true;
141        return false;
142    }
143}
144?>

使用时,当然先要引入上面那个文件了,然后通过下面的代码取得当页要显示的记录集,同时也得到了你要的分页连接:
 1<?php
 2@$page_no = $_GET['page_no'];
 3
 4$sql = "你的 sql 语句,可以复杂点的";
 5
 6$pagination = new FN_Pagination($sql,'admin.php?page=my_plugin/tracking-logs.php',$page_no);
 7$records = $pagination->get_results();
 8
 9//然后列表循环显示你的 $records 记录
10?>
11
12<?php /** 然后在你想要放置翻页链接的地方加上下面的代码,注意 <div> 层次,以运用正确的样式**/?>
13<div class="tablenav">
14    <?php if ( $pagination->results_are_paged() ) : ?>
15        <div class="tablenav-pages"><?php $pagination->page_links(); ?></div>
16    <?php endif; ?>
17</div>

就这样,整个过程就完成了,看看页面是不是你想要的结果。上面的分页类暂时未加入条件搜索和排序的支持,以后还得进一步扩充的。 永久链接 https://yanbin.blog/admin-pagination/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。