[WP]管理画面にカッコいいテーブルを埋め込む

投稿者 admin on October 18, 2012

Wordpressのプラグインの開発をしていると、専用の設定画面を作り、さらにテーブルを作って色々なデータを表示したい時がある。

その場合、別に普通にスタイリングして行っても構わないが、出来る限り管理画面内の要素は標準化したいし、その方が簡単に美しいテーブルが作れる。

その方法としては

1・他の画面で使われているhtmlのクラスなどをそっくり真似てマークアップする

2・管理画面APIを使う の方法が考えられる。

単純なものや、大きさが割と決まっているようなものは1の方法で充分だろう。ただ、データの個数が増えて行って、ページングなどもつけたい場合、自前でガリガリ作り込むのはかなりしんどいので、ここは2の方法を選択したい。

あまり知られていないが、WPのコアにはWP_List_Tableという、テーブルを描画するための専用のクラスがあり、公式にもドキュメントが存在する(英文)

http://codex.wordpress.org/Function_Reference/WP_List_Table

このクラスが定義されていない風のエラーが出た時は、自前でインクルードする。

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

基本の使い方は以下

class Example_List_Table extends WP_List_Table {}
$example_lt = new Example_List_Table();

クラスを拡張し、さらにインスタンスを生成する。 もちろん、これだけでは何も出てこない。 クラス拡張時に適切にメソッドを上書きしたりデータをセットしておく必要がある。 この辺り、公式にはあまり具体的な説明が無いので

http://wp.smashingmagazine.com/2011/11/03/native-admin-tables-wordpress/

この辺りを頼りにすることにしよう。 まずはコンストラクタ。 メンバー変数を上書きして、自分仕様にする。 single , plural はラベルのことで、あまり重要ではなさそう。 ajaxはfalseにしてあるが、これはこのテーブルにおいてajaxを使うかどうか(どこからどこに対してのajaxなのか、今の時点では不明だが、使わない事が決まっていればfalse)

class Link_List_Table extends WP_List_Table {

	/**
	 * Constructor, we override the parent to pass our own arguments
	 * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
	 */
	 function __construct() {
		 parent::__construct( array(
		'singular'=> 'wp_list_text_link', //Singular label
		'plural' => 'wp_list_test_links', //plural label, also this well be one of the table css class
		'ajax'	=> false //We won't support Ajax for this table
		) );
	 }

}

次に、カラム(列)の設定。 これは重要そうだ。 get_columns()というメソッドを追加する。

/**
 * Define the columns that are going to be used in the table
 * @return array $columns, the array of columns to use with the table
 */
function get_columns() {
	return $columns= array(
		'post_id'=>__('ID'),
		'post_name'=>__('Name'),
		'post_title'=>'タイトル'
	);
}

フィールド名はDBのカラム名と合わせおく。 大変便利な事に、このクラスではカラムのソートがサポートされている。ソートのあるなしを設定するために、メソッドを追加。

/**
 * Decide which columns to activate the sorting functionality on
 * @return array $sortable, the array of columns that can be sorted by the user
 */
public function get_sortable_columns() {
	return $sortable = array(
		'post_id'=>'post_id'
	);
}

get_sortable_columns()というメソッドを追加して、ソートしたい項目を持つarrayを返せば良い・・・ここでも各要素の値は、DBのフォールド名と一致させる。

さてここまでで基本の骨格が決まるので、あとはデータを流し込むだけ・・・と言いたい所だが、この流し込み作業が実は少々骨が折れる。

/**
 * Prepare the table with different parameters, pagination, columns and table elements
 */
function prepare_items() {
	global $wpdb, $_wp_column_headers;
	$screen = get_current_screen();

	/* -- Preparing your query -- */
        $query = "SELECT * FROM $wpdb->links";

	/* -- 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) || $pagedset_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[$screen->id]=$columns;

	/* -- Fetch the items -- */
		$this->items = $wpdb->get_results($query);
}

一見複雑そうだが、要するにDBからのフェッチ。ページング情報に合わせて取得するデータを調整している。 取得したデータは $this->items というインスタンス変数に入る。 ページ当たりの表示数は $perpage に直に代入されているので、自分仕様に合わせておく。 そしていよいよデータの描画だ。

/**
 * Display the rows of records in the table
 * @return string, echo the markup of the rows
 */
function display_rows() {

	//Get the records registered in the prepare_items method
	$records = $this->items;

	//Get the columns registered in the get_columns and get_sortable_columns methods
	list( $columns, $hidden ) = $this->get_column_info();

	//Loop for each record
	if(!empty($records)){foreach($records as $rec){

		//Open the line
        echo '< tr id="record_'.$rec->link_id.'">';
		foreach ( $columns as $column_name => $column_display_name ) {

			//Style attributes for each col
			$class = "class='$column_name column-$column_name'";
			$style = "";
			if ( in_array( $column_name, $hidden ) ) $style = ' style="display:none;"';
			$attributes = $class . $style;

			//edit link
			$editlink  = '/wp-admin/link.php?action=edit&link_id='.(int)$rec->link_id;

			//Display the cell
			switch ( $column_name ) {
				case "col_link_id":	echo '< td '.$attributes.'>'.stripslashes($rec->link_id).'< /td>';	break;
				case "col_link_name": echo '< td '.$attributes.'>'.stripslashes($rec->link_name).'< /td>'; break;
				case "col_link_url": echo '< td '.$attributes.'>'.stripslashes($rec->link_url).'< /td>'; break;
				case "col_link_description": echo '< td '.$attributes.'>'.$rec->link_description.'< /td>'; break;
				case "col_link_visible": echo '< td '.$attributes.'>'.$rec->link_visible.'< /td>'; break;
			}
		}

		//Close the line
		echo'< /tr>';
	}}
}

取得したデータをループで回してechoしている。 このメソッドは実は元クラスに含まれているので、書かなくても問題は無いようだ。ただ、きめ細かく表示を調整したい場合、このコードをいじれば自由自在にカスタマイズ出来るはずだ。

最後に、以下のメソッドも必要だった。

public function column_default($item, $column_name){
	return $item -> $column_name;
}

これは一行分のデータが$itemとして入って来るので、その中のどのデータを返すかを指示する。こんな処理が必要なのか疑問だが、素直に、$column_nameで示されたデータを返せば良い。

逆に言うと、書かなくてはいけないメソッドは以下の3つ

get_columns()

prepare_items()

column_default()

以上ですべての準備が整ったので、表示させたい部分に次のコードを入れる

//Prepare Table of elements
$wp_list_table = new Links_List_Table();
$wp_list_table->prepare_items();
 //Table of elements $wp_list_table->display();

 

簡単、とは言っておきながら実際ここまで来るのに時間はかかるし、厄介なものだ。さらに、実はこの後ヘッダー部分のソートボタンを出力する時のバグ?を発見し、その部分のメソッドもコアから取って来ていじるハメになってしまった。

ただし、一度作っておけば、様々な場面で再利用出来るし、何よりも仕上がりが良い。クラスをそっくり真似る静的な手法とも合わせて、プラグイン開発者は是非身に付けておくと良いと思う。

コメントをどうぞ

投稿者 Guestbeink 日時
guest test post
bbcode
html
http://temresults2018.com/ simple
投稿者 Guestbeink 日時
guest test post
bbcode
html
http://temresults2018.com/ simple
コメントを残す



(このメールアドレスは表示されません。)


Captcha認証コード

Captchaをクリックすると違う文字候補が出てきます。


Tags