很多时候我们想把自己的主题制作成能够支持在后台添加一个菜单,并且列出自己创建表的数据,那么怎么做了,别急,下面我就分享下我自己的。
首先找到你自己主题下面的function.php,然后在里面加上如下代码
然后就在你的主题下面新建一个class-wp-attendance-list-table.php文件
有部分代码我是直接复制原来的,所以有的变量没变,其实也没啥的,能用就行,呵呵~~
就像下面的这个效果:
在这个例子中我新建了一个表,用于记录活动的,下面是sql,你可以用sql工具导进去
-- ----------------------------
-- Table structure for `wp_participate_history`
-- ----------------------------DROP TABLE IF EXISTS `wp_participate_history`;
CREATE TABLE `wp_participate_history` (
`par_id` int(11) NOT NULL auto_increment,
`par_postid` int(11) NOT NULL,
`par_posttitle` text NOT NULL,
`par_type` varchar(20) default NULL,
`par_userid` int(10) NOT NULL default '0',
`par_username` varchar(50) NOT NULL,
`par_time` int(11) NOT NULL,
`get_sticker` int(11) NOT NULL,
`status` int(1) NOT NULL default '0',
PRIMARY KEY (`par_id`)
) ENGINE=MyISAM AUTO_INCREMENT=213 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of wp_participate_history
-- ----------------------------
INSERT INTO `wp_participate_history` VALUES ('7', '1366', 'eeeeeeeeeeeeeeee', 'event', '1', 'Administrator', '1354700553', '20', '2');
INSERT INTO `wp_participate_history` VALUES ('10', '1349', 'For Everyone', 'everyone', '2', 'test', '1354756577', '0', '1');
首先找到你自己主题下面的function.php,然后在里面加上如下代码
add_action('admin_menu', 'add_menu_items');
function add_menu_items(){
add_menu_page(__('Attendance'), __('Attendance'), 8, 'manage_attendence', 'my_attendance_render', '', 7);
}
function my_attendance_render() {
require_once TEMPLATEPATH . '/class-wp-attendance-list-table.php';
}
然后就在你的主题下面新建一个class-wp-attendance-list-table.php文件
下面我们就来制作自己的list-table了
/**
* @author Gyrate
* @link
* @name
* @version 1.0
*
* 如果你想看下本例子的效果:把下来的php代码粘贴到你主题下面的function.php里面,然后再在数据库中运行下面的sql语句即可
* To use this example,just put this file into your theme directory.and add the code below into your function.php
* Then run the sql code in your database
* CODE TO function.php:
add_action('admin_menu', 'add_menu_items');
function add_menu_items(){
add_menu_page(__('Attendance'), __('Attendance'), 8, 'manage_attendence', 'my_attendance_render', '', 7);
}
function my_attendance_render() {
require_once TEMPLATEPATH . '/class-wp-attendance-list-table.php';
}
* SQL CODE:
DROP TABLE IF EXISTS `wp_participate_history`;
CREATE TABLE `wp_participate_history` (
`par_id` int(11) NOT NULL auto_increment,
`par_postid` int(11) NOT NULL,
`par_posttitle` text NOT NULL,
`par_type` varchar(20) default NULL,
`par_userid` int(10) NOT NULL default '0',
`par_username` varchar(50) NOT NULL,
`par_time` int(11) NOT NULL,
`get_sticker` int(11) NOT NULL,
`status` int(1) NOT NULL default '0',
PRIMARY KEY (`par_id`)
) ENGINE=MyISAM AUTO_INCREMENT=213 DEFAULT CHARSET=utf8;
INSERT INTO `wp_participate_history` VALUES ('7', '1366', 'test title', 'event', '1', 'Administrator', '1354700553', '20', '2');
INSERT INTO `wp_participate_history` VALUES ('10', '1349', 'For Everyone', 'everyone', '2', 'test', '1354756577', '0', '1');
*/
/*1.0首先我们得确保能够继承WP_List_Table类
*(we should make sure that we can use WP_List_Table)
* */
if(!class_exists('WP_List_Table')){
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
//2.0一些定义(some defines that may use in the example)
global $wpdb;
defined("TABLE_PARTICIPTE_HISTORY") || define("TABLE_PARTICIPTE_HISTORY", $wpdb->prefix . "participate_history");
defined("CUSTOM_POST_TYPE1") || define('CUSTOM_POST_TYPE1','event');
/* 3.0
* ====================================================================================
* --+ 创建类,我会解释每个类的作用的和写的步骤 +--
* --+ (create our list class,I have give +--
* --+ the steps and alse some explanation of functions) +--
* --+ start Attendance_List_Table +--
* ====================================================================================
*/
//
class Attendance_List_Table extends WP_List_Table {
public $screen;
public $redirect='admin.php?page=manage_attendence';
/**
* 3.1
* 构造方法,用于设置一些默认的参数、筛选条件、需要覆盖的配置等,当然也可以定义下你自己的这个列表支持不支持ajax
* Constructor. This sets default arguments and filters. Developers should override this,
* calling the parent constructor to provide values for singular and plural labels,
* as well as whether the class supports AJAX.
*/
function __construct() {
$this->screen = get_current_screen();
global $wpdb;
parent::__construct( array(
'plural' => 'attendance',
'singular' => 'attendance',
'ajax' => false
));
}
/**
* 3.2
* 这个方法主要是设置下需要显示的数据、处理一下排序、分页和其他操作什么的,不过次方法父类是不会自动加载,需要在调用类处调用下
* Developers should use this class to query and filter data, handle sorting, and pagination,
* and any other data-manipulation required prior to rendering.
* This method should be called explicitly after instantiating your class, and before rendering.
*/
function prepare_items() {
global $wpdb, $_wp_column_headers,$attendance_search;
$attendance_search = isset( $_REQUEST['s'] ) ? trim( $_REQUEST['s'] ) : $attendance_search;
$attendance_status = isset( $_REQUEST['attendance_status'] ) ? (int) trim( $_REQUEST['attendance_status'] ) : 0;
$where=' WHERE 1=1';
$attendance_status&& $where.=" AND status=$attendance_status";
$attendance_search&& $where.=" AND par_posttitle LIKE '%$attendance_search%' ";
/* -- Preparing your query -- */
$query = "SELECT * FROM ".TABLE_PARTICIPTE_HISTORY." $where";
/* -- Ordering parameters -- */
//Parameters that are going to be used to order the result
$orderby = !empty($_GET["orderby"]) ? mysql_real_escape_string($_GET["orderby"]) : 'ASC';
$order = !empty($_GET["order"]) ? mysql_real_escape_string($_GET["order"]) : '';
if(!empty($orderby) & !empty($order)){ $query.=' ORDER BY '.$orderby.' '.$order; }
/* -- Pagination parameters -- */
//Number of elements in your table?
$totalitems = $wpdb->query($query); //return the total number of affected rows
//How many to display per page?
$perpage = 5;
//Which page is this?
$paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : '';
//Page Number
if(empty($paged) || !is_numeric($paged) || $paged< =0 ){ $paged=1; }
//How many pages do we have in total?
$totalpages = ceil($totalitems/$perpage);
//adjust the query to take pagination into account
if(!empty($paged) && !empty($perpage)){
$offset=($paged-1)*$perpage;
$query.=' LIMIT '.(int)$offset.','.(int)$perpage;
}
/**
* 3.2.1
* -- 分页设置Register the pagination --
* 这个是必须要的,也就是说上面的几行代码都是为这个做准备的,此方法会在父类中自动调用,所以在这里你就需要设置下分页的相关参数
* 有三个参数,这里说明下:
* total_items——总共有多少条数据
* per_page——每页显示的数据,你懂的
* total_pages——总共页码,一般都是ceil(总条数/每页现实数);
* This method should be called internally (usually from prepare_items()) to set basic pagination arguments. Available arguments include:
* total_items - the total number of items to be displayed. Usually as simple as count($data)
* per_page - the number of items to show per page
* total_pages - the total number of pages. Can be left blank or calculated manually, like so: ceil($total_items/$per_page)
*/
$this->set_pagination_args( array(
"total_items" => $totalitems,
"total_pages" => $totalpages,
"per_page" => $perpage,
) );
//The pagination links are automatically built according to those parameters
/* -- Register the Columns -- */
$columns = $this->get_columns();
$_wp_column_headers[$this->screen->id]=$columns;
$this->_column_headers = array(
$this->get_columns(), // columns
array(), // hidden
$this->get_sortable_columns(), // sortable
);
/* -- Fetch the items -- */
$this->items = $wpdb->get_results($query);
}
/**
* 3.3
* 当查询没有数据的时候,在循环的li里面默认显示,当然这个你也可以不用再写,无关紧要
* Returns the message to be displayed when there are no items.
*/
function no_items() {_e( 'No Attendance found.' );}
/**
* 3.4
* 这个主要是用于来自定义列表右边的搜索框,这个方法里面你需要中心写下搜索框的代码,世界输出一个搜索的表格即可,
* 当然要是你没啥特别要求的话,可以不用定义这个,无关紧要
* This renders a search box. To use this, you will still need to manually wrap your list table (including search box) in a form.
*/
//function search_box() {}
/**
* 3.5
* 这个主要是用于来定义上面的显示结果的分类,就像我们看到用户列表中就分了不同的角色来显示,在这里我就分了所以的、出席了的和只报名了的
* Returns an associative array listing all the views that can be used with this table.
*/
function get_views(){
$attendance_status=$this->get_attendance_status();
$attendance_count=$this->get_status_count();
foreach ($attendance_status as $status=>$desc){
$_REQUEST["attendance_status"]==$status && $class='class="current"';
$status_attendance[] = "<a $class href='" . esc_url( add_query_arg( 'attendance_status', $status, $this->redirect ) ) . "'>".sprintf( _nx( ''.$desc.' <span class=count>(%s)</span>', ''.$desc.' <span class=count>(%s)</span>', $attendance_count[$status], 'posts' ), number_format_i18n( $attendance_count[$status] ) ) ."</a>";
unset($class);
}
return $status_attendance;
}
/**
* 这两个函数:get_status_count()和get_attendance_status()都是我自己定义的,非父类所要求,这个你可以跳过
* get_status_count()and get_attendance_status() are not extended from father class,they are just my customizing functions,just skip
*/
function get_status_count(){
global $wpdb;
$attendance_status=$this->get_attendance_status();
foreach ($attendance_status as $status=>$desc){
$status && $where=" WHERE status=".(int)$status;
$count[$status]=$wpdb->get_var("SELECT count(par_id) sum FROM ".TABLE_PARTICIPTE_HISTORY." $where");
}
return $count;
}
function get_attendance_status(){
return array(
0=>"All",
1=>"Attended",
2=>"Has Singed"
);
}
/**
* 3.6
* 这个方法主要是用来显示批量操作的,像批量删除、批量通过等等,以下拉列表的方式显示,我这里的identify主要是用于确认出席的操作
* Override this method to return an associative array ( action_slug => action_title ) containing all the bulk actions available for the table.
*/
function get_bulk_actions() {
return array(
'delete' => __( 'Delete' ),
'identify' => __( 'Identified' )
);
}
/**
* 3.7
* 主要显示thead的部分,懂吧?返回的格式就是我写的那样
* This method should be overridden to return an associative array of columns.
* The associative array should follow the format 'slug'=>'Title'
* and is frequently used to provide part of the _column_headers property.
*/
function get_columns() {
return array(
'cb' => '<input type="checkbox" />',
'par_posttitle'=>__('Items Name'),
'par_username'=>__('User Name'),
'get_sticker'=>__('Paid Sticker'),
'par_type'=>__('Attendance Type'),
'status'=>__('Status'),
'par_time'=>__('Sing Time'),
);
}
/**
* 3.8
* 此方法主要是用来列出那些字段需要排序的,也就是我们看到的table上面的thead上可以点击排序的那些字段
* This method should be overridden to return an associative array of columns that you want to make sortable.
* The associative array should follow the format 'column_slug'=>array('sortby',true),
* where the second property states whether the field is presorted.
* This is frequently used to provide part of the _column_headers property.
*/
public function get_sortable_columns() {
return array(
'par_posttitle'=>array('par_posttitle',false),
'par_time'=>array('par_time',false),
'get_sticker'=>array('get_sticker',false),
);
}
/**
* 3.9
* 主要是显示所有查询出来的的数据
* This loops through the items property and renders them to the page as table rows.
* Generally, you don't need to call this explicitly as it is handled automatically on display().
*/
function display_rows() {
foreach ( $this->items as $userid => $attendance_object ) {
$style = ( ' class="alternate"' == $style ) ? '' : ' class="alternate"';
echo "\n\t", $this->single_row( $attendance_object, $style);
}
}
/**
* 3.10
* 主要是显示所有查询出来每一条数据
* This echos a single item (from the items property) to the page.
* Generally, you don't need to call this explicitly as it is handled automatically on display().
*/
function single_row( $attendance_object, $style = '') {
list( $columns, $hidden ) = $this->get_column_info();
$r = "<tr id='atendance-$attendance_object->par_id'$style>";
$checkbox = '<label class="screen-reader-text" for="cb-select-' . $attendance_object->par_id . '">' . sprintf( __( 'Select %s' ), $attendance_object->par_id ) . '</label>'
. "<input type='checkbox' name='users[]' id='user_{$attendance_object-/>par_id}' value='{$attendance_object->par_id}' />";
$actions = array();
$attendance_object->status==1&&$actions['identify'] = "<a href='" . wp_nonce_url( "$this->redirect&action=identify&users=$attendance_object->par_id", 'bulk-users' ) . "'>" . __( 'Identify' ) . "</a>";
$actions['delete'] = "<a href='" . wp_nonce_url( "$this->redirect&action=delete&users=$attendance_object->par_id", 'bulk-users' ) . "'>" . __( 'Delete' ) . "</a>";
$edit .= $this->row_actions( $actions );
foreach ( $columns as $column_name => $column_display_name ) {
$class = "class=\"$column_name column-$column_name\"";
$style = '';
if ( in_array( $column_name, $hidden ) )$style = ' style="display:none;"';
$attributes = "$class$style";
switch ( $column_name ) {
case 'cb':
$r .= "<th scope='row' class='check-column'>$checkbox</th>";
break;
case 'par_posttitle':
$r .= "<td $attributes>$attendance_object->par_posttitle $edit</td>";
break;
case 'par_type':
$estr=$attendance_object->par_type==CUSTOM_POST_TYPE1 ? "Event" : "Activity For ".$attendance_object->par_type;
$r .= "<td $attributes>$estr</td>";
break;
case 'par_username':
$r .= "<td $attributes>$attendance_object->par_username</td>";
break;
case 'par_time':
$r .= "<td $attributes>".date('d/m/Y H:i',$attendance_object->par_time)."</td>";
break;
case 'get_sticker':
$r .= "<td $attributes>$attendance_object->get_sticker</td>";
break;
case 'status':
$attendance_status=$this->get_attendance_status();
$s=$attendance_status[(int)$attendance_object->status] ? $attendance_status[(int)$attendance_object->status] : "unknown";
$r .= "<td $attributes>$s</td>";
break;
default:
/**
* 3.11
* 解释下这里的manage_attendance_custom_column
*/
$r .= "<td $attributes>";
$r .= apply_filters( 'manage_attendance_custom_column', '', $column_name, $attendance_object->par_id );
$r .= "</td>";
break;
}
}// end of foreach
$r .= '</tr>';
return $r;
}// end of single_row
}// end of class
/**
* ====================================================================================
* --+ end of Attendance_List_Table +--
* --+ begin function to handle the list +--
* 下面我就列出你须要重新定义的方法,
* I'll list the functions that must be over-ridden:
* ajax_user_can,prepare_items,get_columns
*
*
* 当你在制作一个简单的列表的时候需要定义一下胰腺癌方法
* while you try to add a simple list,these are the one you should over ride
* __construct,prepare_items,set_pagination_args,get_columns,display_rows,single_row
* ====================================================================================
*/
/**
* 4.0
* 在调用的地方需要的是,怎么去调用
* how to user the class?
* 4.1
* $wp_attendance_list_table=new Attendance_List_Table();
* $wp_attendance_list_table->prepare_items();
* <div class="wrap">
* <h2>title</h2>
* <form id="manage_attendence" action="" method="post">
* $wp_attendance_list_table->display();
* </form>
* </div>
*/
$wp_attendance_list_table=new Attendance_List_Table();
$wp_attendance_list_table->prepare_items();
if ( empty($_REQUEST) ) {
$referer = '<input type="hidden" name="wp_http_referer" value="'. esc_attr(stripslashes($_SERVER['REQUEST_URI'])) . '" />';
} elseif ( isset($_REQUEST['wp_http_referer']) ) {
$redirect = remove_query_arg(array('wp_http_referer', 'updated', 'delete_count'), stripslashes($_REQUEST['wp_http_referer']));
$referer = '<input type="hidden" name="wp_http_referer" value="' . esc_attr($redirect) . '" />';
} else {
$redirect = 'admin.php?page=manage_attendence';
}
global $wpdb;
$action = $wp_attendance_list_table->current_action()?$wp_attendance_list_table->current_action():trim($_REQUEST["action"]);
switch ( $action ) {
case "delete":
if ( empty($_REQUEST['users']) ) {
wp_redirect($redirect);
die();
}
$userids = array_map( 'intval', (array) $_REQUEST['users'] );
$delete_count = 0;
$update = 'del';
foreach ( $userids as $id ) {
$delete_count+=$wpdb->query("DELETE FROM ".TABLE_PARTICIPTE_HISTORY." WHERE par_id = $id ");
}
$redirect = add_query_arg( array('delete_count' => $delete_count, 'update' => $update), $redirect);
wp_redirect($redirect);
break
;
case "identify":
if ( empty($_REQUEST['users']) ) {
wp_redirect($redirect);
die();
}
$userids = array_map( 'intval', (array) $_REQUEST['users'] );
$identify_count = 0;
$update = 'identify';
foreach ( $userids as $id ){
$par_userid=$wpdb->get_var("SELECT par_userid FROM ".TABLE_PARTICIPTE_HISTORY." WHERE par_id = $id ");
$pay_stickers=$wpdb->get_var("SELECT pay_stickers FROM ".TABLE_PARTICIPTE_HISTORY." WHERE par_id = $id ");
$identify_count+=$wpdb->query("UPDATE ".TABLE_PARTICIPTE_HISTORY." SET status=2 WHERE par_id = $id ");
if($identify_count){
update_user_meta($par_userid, "available_stickers", intval(get_user_meta($par_userid,"available_stickers",true))+intval($pay_stickers) );
update_user_meta($par_userid, "collected_stickers", intval(get_user_meta($par_userid,"collected_stickers",true))+intval($pay_stickers) );
}
}
$redirect = add_query_arg( array('identify_count' => $identify_count, 'update' => $update), $redirect);
wp_redirect($redirect);
break
;
}
$messages = array();
if ( isset($_GET['update']) ) {
switch($_GET['update']) {
case 'del':
$delete_count = isset($_GET['delete_count']) ? (int) $_GET['delete_count'] : 0;
$messages[] = '<div id="message" class="updated"><p>' . sprintf( "%s attendaces deleted", $delete_count ) . '</p></div>';
break;
case 'identify':
$identify_count = isset($_GET['identify_count']) ? (int) $_GET['identify_count'] : 0;
$messages[] = '<div id="message" class="updated"><p>' . sprintf( '%s attendaces identify.', $identify_count ) . '</p></div>';
break;
}
};
$attendance_search && $messages[] = printf( '<span class="subtitle">' . __('Search results for “%s”') . '</span>', esc_html( $attendance_search ) ); ;
empty($messages)&&$messages[] = '<div id="message" class="updated"><p>' . __( '"Identify" referes to confirming attendance.' ) . '</p></div>';
?>
< ?php if ( ! empty($messages) ) {foreach ( $messages as $msg )echo $msg;} ?>
<div class="wrap">
< ?php screen_icon("users"); ?>
<h2>< ?php _e('Manage Attendence'); ?></h2>
< ?php $wp_attendance_list_table->views(); ?>
<form id="manage_attendence" action="admin.php?page=manage_attendence" method="post">
< ?php $wp_attendance_list_table->search_box( __( 'Search Attendence' ),'attendence' ); ?>
< ?php $wp_attendance_list_table->display(); ?>
</form>
<br class="clear" />
</div>
有部分代码我是直接复制原来的,所以有的变量没变,其实也没啥的,能用就行,呵呵~~