listテーブル をカスタム管理ページに追加しようとしています。 このガイド and このリファレンス実装をフォローしています 。
残念ながら、データを追加するために$this->items
を定義すると、管理ページに nothing が表示され(リストテーブルの周りのhtmlでもない)、エラーメッセージは表示されません。その行をコメントアウトすると(135
行)、明らかにデータが欠落していることを除いてそれは機能します。
私のコード:
<?php
add_action('admin_menu', 'add_example_menues');
function add_example_menues() {
add_menu_page('test', 'test', 'administrator', 'test-top', 'build_test_page');
add_submenu_page('test-top', 'All tests', 'All tests', 'administrator', 'test-top');
}
if(!class_exists('WP_List_Table')){
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class test_List_Table extends WP_List_Table {
function __construct() {
parent::__construct( array(
'singular' => 'test',
'plural' => 'tests',
'ajax' => false
));
}
function extra_tablenav ($which) {
if ($which == "top") {
echo "Top";
}
if ($which == "bottom") {
echo "Bottom";
}
}
function get_columns() {
$columns = array(
'id' => 'ID',
'title' => 'Title',
'user_id' => 'User ID',
'description' => 'Description'
);
return $columns;
}
function get_sortable_columns() {
return $sortable = array(
'id' => array('id',false),
'title' => array('title',false),
'user_id' => array('user_id',false)
);
}
function prepare_items() {
global $wpdb;
//data normally gotten from non-wp database. Wordpress db user has access, as per this SE post:
//http://wordpress.stackexchange.com/questions/1604/using-wpdb-to-connect-to-a-separate-database
$query = "SELECT `id`, `title`, `user_id`, `description` FROM otherdb.example_table";
//pagination stuff
$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; }
$totalitems = $wpdb->query($query);
echo "$totalitems";
$per_page = 5;
$paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : '';
if(empty($paged) || !is_numeric($paged) || $paged<=0 ){ $paged=1; }
$totalpages = ceil($totalitems/$perpage);
if(!empty($paged) && !empty($perpage)){
$offset=($paged-1)*$perpage;
$query.=' LIMIT '.(int)$offset.','.(int)$perpage;
}
$this->set_pagination_args( array(
"total_items" => 4,
"total_pages" => 1,
"per_page" => 5,
) );
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
//actual data gotten from database, but for SE use hardcoded array
//$data = $wpdb->get_results($query, ARRAY_N);
$example_data = array(
array(
'id' => 1,
'title' => 'nonsense',
'user_id' => 1,
'description' => 'asdf'
),
array(
'id' => 2,
'title' => 'notanumber',
'user_id' => 2,
'description' => '404'
),
array(
'id' => 3,
'title' => 'I Am A Title',
'user_id' => 3,
'description' => 'desc'
),
array(
'id' => 4,
'title' => 'Example',
'user_id' => 4,
'description' => 'useless'
),
array(
'id' => 5,
'title' => 'aeou',
'user_id' => 5,
'description' => 'keyboard layouts'
),
array(
'id' => 6,
'title' => 'example data',
'user_id' => 6,
'description' => 'data example'
),
array(
'id' => 7,
'title' => 'last one',
'user_id' => 7,
'description' => 'done'
)
);
//This is the line:
$this->items = $example_data;
//When the above line is commented, it works as expected (except for the lack of data, of course)
}
}
function build_test_page() {
$testListTable = new test_List_Table();
$testListTable->prepare_items();
?>
<div class="wrap">
<div id="icon-users" class="icon32"><br/></div>
<h2>List Table Test</h2>
<?php $testListTable->display() ?>
</div>
<?php
}
?>
上記のコードは、require_once()
とともにfunctions.php
に含まれる別のファイルにあります。
私はワードプレス4.1.1を使用しています
ここで何が起こっているの?なぜeverythingが消えてエラーが出ないのでしょうか?
最初にWP_List_Table
を実装したときにも同じエラーをしました。
問題は、WP_List_Table::display()
WordPressを順番に呼び出すと、次のことが呼び出されることです。
最後の関数は行ごとに呼び出されます。そのコードを見れば( source を見てください)、それは持っています:
if ( 'cb' == $column_name ) {
// you don't have 'cb' column, code remove because not relevant
} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
// you don't have method named 'column_{$column_name}',
// code remove because not relevant
} else {
// not relevant line
echo $this->column_default( $item, $column_name );
}
そのためWordPressはすべての行に対してWP_List_Table::column_default()
を呼び出しますが、そのメソッド は存在しません 。
あなたのクラスに追加:
public function column_default($item, $column_name) {
return $item[$column_name];
}
そしてあなたのデータは正しく表示されます。
データを追加しないと、エラーが発生しません。データがないと、WordPressはdisplay_rows()
やその後の他のメソッドを呼び出しません。
prepare_items()
メソッドでは変数$perpage
を使用しますが、$per_page
として定義すると(アンダースコアに注意してください)、ゼロ除算の警告が発生します(そしてページ付けは機能しません)
コードmysql_real_escape_string($_GET["orderby"])
は not safeです。なぜなら'orderby'
SQL句のmysql_real_escape_string()
では十分ではないからです。 ( 最近のYoast SQLインジェクションのバグ を参照).
次のようにしてください。
$orderby = 'id'; // default
$by = strtolower(filter_input(INPUT_GET, 'orderby', FILTER_SANITIZE_STRING));
if (in_array($by, array('title', 'description', 'user_id'), true) {
$orderby = $by;
}
そして'order'
節にも似たようなことをしてください:たぶんそれはASC
かDESC
のどちらかであることができるだけです:他に何も許さないでください。
今家にいる、私は実際にあなたのコードを実行しました。私はこれを得た:
致命的なエラー:.../wp-admin/includes/class-wp-list-table.phpの88行目の未定義関数convert_to_screen()を呼び出す
注:
開発時には Debugging_in_WordPress をオンにしてください。
とにかくこれは私をStackoverflowについての次の質問に導きました:
@ brasofiloの回答は大いに役に立ちましたが、彼はWordPress Developmentの大手企業の1人なので、驚くことではありません。
とにかく彼の答えに続いて、あなたはメソッドcolumn_default
が欠けています、さらに_construct
メソッドは異なっています。しかし、あなたは自分自身でそれを読むことができます、ここでいくつかの実用的な - 削除された - コードがあります:
add_action( 'admin_menu', 'add_test_list_table_menues' );
function add_test_list_table_menues() {
add_menu_page(
'test',
'test',
'manage_options',
'test-top',
'test_list_table_output'
);
}
function test_list_table_output() {
echo '<div class="wrap">';
echo '<h2>Test List Table</h2>';
new Test_List_Table();
echo '</div>';
}
if( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class Test_List_Table extends WP_List_Table {
public function __construct() {
parent::__construct( array(
'singular' => 'test',
'plural' => 'tests',
'ajax' => false
));
$this->prepare_items();
$this->display();
}
function get_columns() {
$columns = array(
'tid' => 'ID',
'title' => 'Title',
'user_id' => 'User ID',
'description' => 'Description'
);
return $columns;
}
function column_default( $item, $column_name ) {
switch( $column_name ) {
case 'tid':
case 'title':
case 'user_id':
case 'description':
return $item[ $column_name ];
default:
return print_r( $item, true ) ;
}
}
function prepare_items() {
$example_data = array(
array(
'tid' => 1,
'title' => 'nonsense',
'user_id' => 1,
'description' => 'asdf'
),
array(
'tid' => 2,
'title' => 'notanumber',
'user_id' => 2,
'description' => '404'
),
array(
'tid' => 3,
'title' => 'I Am A Title',
'user_id' => 3,
'description' => 'desc'
),
array(
'tid' => 4,
'title' => 'Example',
'user_id' => 4,
'description' => 'useless'
),
array(
'tid' => 5,
'title' => 'aeou',
'user_id' => 5,
'description' => 'keyboard layouts'
),
array(
'tid' => 6,
'title' => 'example data',
'user_id' => 6,
'description' => 'data example'
),
array(
'tid' => 7,
'title' => 'last one',
'user_id' => 7,
'description' => 'done'
)
);
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
$this->items = $example_data;
}
}