深入理解 WordPress `wp_list_table` 类的源码:如何通过 `get_columns()` 和 `get_sortable_columns()` 方法构建表格。

各位观众老爷,晚上好!我是你们的老朋友,今天呢,咱们不聊风花雪月,聊聊 WordPress 里一个看似不起眼,但却非常重要的类:WP_List_Table。 别怕,虽然名字听起来有点高冷,但实际上,只要你掌握了它的精髓,就能轻松驾驭 WordPress 后台的各种列表,打造出让用户尖叫的界面。

今天咱们的重点是:如何通过 get_columns()get_sortable_columns() 方法构建表格。 这两个方法是 WP_List_Table 的核心,理解它们,你就理解了列表的骨架。

一、 WP_List_Table 是个啥?

首先,简单介绍一下 WP_List_Table。 它是 WordPress 提供的一个抽象类,专门用来生成后台管理界面的列表。 想象一下,你在 WordPress 后台看到的文章列表、用户列表、插件列表,等等,很多都是基于 WP_List_Table 来实现的。

这个类提供了一套标准化的方法,让你能够方便地定义列表的列、排序方式、批量操作等等。 它就像一个强大的乐高积木,你可以根据自己的需求,拼装出各种各样的列表。

二、 get_columns():定义表格的列

get_columns() 方法的作用非常直接:定义表格的列及其标题。 它返回一个数组,数组的键是列的 ID(也称为 slug),值是列的标题。

举个例子,假设我们要创建一个自定义的列表,显示一些书籍的信息,包括书名、作者、出版日期,那么 get_columns() 方法可以这样写:

<?php
class My_Books_List_Table extends WP_List_Table {

    function get_columns() {
        $columns = array(
            'cb'        => '<input type="checkbox" />', // 添加一个 checkbox 用于批量操作
            'title'     => '书名',
            'author'    => '作者',
            'pub_date'  => '出版日期'
        );
        return $columns;
    }
}
?>

在这个例子中,我们定义了四个列:

  • cb: 这是一个特殊的列,用于显示复选框,方便用户进行批量操作。注意它的值是一段 HTML 代码,直接输出一个 checkbox。
  • title: 书名,标题是 "书名"。
  • author: 作者,标题是 "作者"。
  • pub_date: 出版日期,标题是 "出版日期"。

注意: 列的 ID (例如 ‘title’, ‘author’, ‘pub_date’) 在后续的方法中会被用到,用来标识不同的列。

三、 get_sortable_columns():定义可排序的列

get_sortable_columns() 方法的作用是:定义哪些列可以进行排序。 它也返回一个数组,数组的键是列的 ID,值是一个包含排序信息的数组。

排序信息数组通常包含两个元素:

  • orderby: 用于排序的参数名。 当用户点击该列的标题进行排序时,WordPress 会在 URL 中添加一个 orderby 参数,值为这里定义的值。
  • asc: 一个布尔值,表示默认的排序方式是升序 (true) 还是降序 (false)。

继续上面的书籍列表的例子,假设我们希望可以按照书名和出版日期进行排序,那么 get_sortable_columns() 方法可以这样写:

<?php
class My_Books_List_Table extends WP_List_Table {

    function get_sortable_columns() {
        $sortable_columns = array(
            'title'     => array('title', true),     // true 表示默认升序
            'pub_date'  => array('pub_date', false)    // false 表示默认降序
        );
        return $sortable_columns;
    }

}
?>

在这个例子中,我们定义了两个可排序的列:

  • title: 可以按照书名进行排序,排序参数是 title,默认升序。
  • pub_date: 可以按照出版日期进行排序,排序参数是 pub_date,默认降序。

四、 将 get_columns()get_sortable_columns() 结合起来

现在,我们将 get_columns()get_sortable_columns() 方法放在一起,看看如何构建一个简单的可排序的列表:

<?php

if ( ! class_exists( 'WP_List_Table' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

class My_Books_List_Table extends WP_List_Table {

    function __construct() {
        parent::__construct( array(
            'singular' => 'book',     // 单数形式
            'plural'   => 'books',    // 复数形式
            'ajax'     => false        // 是否支持 AJAX
        ) );
    }

    function get_columns() {
        $columns = array(
            'cb'        => '<input type="checkbox" />', // 添加一个 checkbox 用于批量操作
            'title'     => '书名',
            'author'    => '作者',
            'pub_date'  => '出版日期'
        );
        return $columns;
    }

    function get_sortable_columns() {
        $sortable_columns = array(
            'title'     => array('title', true),     // true 表示默认升序
            'pub_date'  => array('pub_date', false)    // false 表示默认降序
        );
        return $sortable_columns;
    }

    function prepare_items() {
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();

        $this->_column_headers = array($columns, $hidden, $sortable);

        // 模拟一些数据
        $data = array(
            array('ID' => 1, 'title' => '百年孤独', 'author' => '加西亚·马尔克斯', 'pub_date' => '1967-05-30'),
            array('ID' => 2, 'title' => '追风筝的人', 'author' => '卡勒德·胡赛尼', 'pub_date' => '2003-05-29'),
            array('ID' => 3, 'title' => '小王子', 'author' => '安托万·德·圣-埃克苏佩里', 'pub_date' => '1943-04-06'),
        );

        // 排序
        $orderby = !empty($_GET["orderby"]) ? $_GET["orderby"] : 'title';
        $order = !empty($_GET["order"]) ? $_GET["order"] : 'asc';

        usort( $data, function( $a, $b ) use ( $orderby, $order ) {
            $result = strcmp( $a[$orderby], $b[$orderby] );
            return ( $order === 'asc' ) ? $result : -$result;
        });

        $this->items = $data;

    }

    function column_default( $item, $column_name ) {
        switch( $column_name ) {
            case 'title':
            case 'author':
            case 'pub_date':
                return $item[ $column_name ];
            default:
                return print_r( $item, true ); //Show the whole array for troubleshooting purposes
        }
    }

    function column_cb($item) {
        return sprintf(
            '<input type="checkbox" name="book[]" value="%s" />', $item['ID']
        );
    }

}

// 使用示例
function my_add_menu_items(){
    add_menu_page( '书籍列表', '书籍列表', 'manage_options', 'my_books_list', 'my_render_list_page' );
}
add_action( 'admin_menu', 'my_add_menu_items' );

function my_render_list_page(){
    $myListTable = new My_Books_List_Table();
    $myListTable->prepare_items();
    ?>
    <div class="wrap">
        <h2>书籍列表</h2>
        <form method="post">
            <input type="hidden" name="page" value="tt_test_list_table">
            <?php
            $myListTable->display();
            ?>
        </form>
    </div>
    <?php
}
?>

这段代码做了这些事情:

  1. 定义 My_Books_List_Table 类: 继承自 WP_List_Table, 这是必须的。
  2. __construct() 构造函数: 初始化一些参数,比如单复数形式的名称。
  3. get_columns(): 定义了表格的列,包括书名、作者、出版日期,以及一个用于批量操作的复选框。
  4. get_sortable_columns(): 定义了书名和出版日期可以进行排序。
  5. prepare_items(): 这个方法非常重要,用来准备要显示的数据。 这里我们模拟了一些书籍数据,并且根据 URL 中的 orderbyorder 参数对数据进行了排序。
  6. column_default(): 这个方法用来显示默认的列的内容。 它根据列的 ID,从数据数组中取出对应的值。
  7. column_cb(): 这个方法用来显示复选框列的内容。
  8. my_add_menu_items(): 创建一个后台菜单。
  9. my_render_list_page(): 渲染列表页面,创建 My_Books_List_Table 实例,调用 prepare_items() 准备数据,然后调用 display() 方法显示列表。

这段代码运行后,你就可以在 WordPress 后台看到一个简单的书籍列表,并且可以点击书名和出版日期的标题进行排序。

五、 深入理解: _column_headers 属性

prepare_items() 方法中,有一行代码:

$this->_column_headers = array($columns, $hidden, $sortable);

这行代码非常重要,它将列的信息、隐藏列的信息、以及可排序列的信息,都存储到了 _column_headers 属性中。

_column_headersWP_List_Table 类的一个受保护的属性,它是一个数组,包含三个元素:

  1. $columns: 通过 get_columns() 方法获取的列信息。
  2. $hidden: 一个数组,包含需要隐藏的列的 ID。
  3. $sortable: 通过 get_sortable_columns() 方法获取的可排序列的信息。

WP_List_Table 类在渲染列表的时候,会读取 _column_headers 属性,从而知道要显示哪些列,哪些列可以排序。

六、 扩展:自定义列的内容

除了 column_default() 方法之外,你还可以定义一些自定义的方法,来显示特定列的内容。 方法的名称必须是 column_{列的ID} 的形式。

比如,如果我们要自定义 title 列的内容,可以定义一个 column_title() 方法:

<?php
class My_Books_List_Table extends WP_List_Table {

    function column_title( $item ) {
        // 可以添加链接,或者其他自定义的 HTML 代码
        $actions = array(
            'edit'      => sprintf('<a href="?page=%s&action=%s&book=%s">编辑</a>', $_REQUEST['page'], 'edit', $item['ID']),
            'delete'    => sprintf('<a href="?page=%s&action=%s&book=%s">删除</a>', $_REQUEST['page'], 'delete', $item['ID']),
        );

        return sprintf('%1$s %2$s',
            /*1%s*/ $item['title'],
            /*2%s*/ $this->row_actions($actions)
        );
    }

}
?>

在这个例子中,column_title() 方法为书名添加了编辑和删除的链接。 row_actions()WP_List_Table 提供的一个方法,用来生成操作链接。

七、 总结

今天,我们深入学习了 WP_List_Table 类的 get_columns()get_sortable_columns() 方法。 这两个方法是构建 WordPress 后台列表的基础。

记住,get_columns() 用来定义表格的列及其标题,get_sortable_columns() 用来定义哪些列可以进行排序。

通过灵活运用这两个方法,你可以轻松地创建出各种各样的列表,满足不同的需求。

希望今天的讲座对你有所帮助。 咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注