カスタマイズ 2024.06.14 2024.06.14
WordPressの投稿一覧ページをカスタマイズしてみる【後編 〜実践〜】
目次
はじめに
この記事は、WordPressの投稿一覧ページをカスタマイズしてみる【前編 〜edit.php解説〜】の続きになります。 前回の説明では、edit.phpの中身について説明しました。今回は、edit.phpのリスト部分を表示する際に使用されているWP_List_Tableクラスとその拡張クラスについての解説と、WP_List_Tableクラスを使用して管理画面を作成する手順について説明します。
WP_List_Tableクラスとその拡張クラス
前回の記事では、一覧ページの表示にはWP_List_Tableクラスが使用されていることがわかりました。[^1]しかし、全ての一覧ページでこのクラスが使われているかというとそうではなく、投稿ページではWP_Posts_List_Table、メディアページでは WP_Media_List_Tableクラスといった、WP_List_Tableクラスを拡張したクラスが使われています。 今回はWP_Posts_List_Tableクラスについて説明します。
WP_Posts_List_Tableクラス[^2]
WP_Post_List_Tableクラスは、投稿の一覧ページの表示に使われるクラスで、WP_List_Tableクラスを拡張したものです。拡張クラスであるため、定義されているメソッドやプロパティの名前は同じですが、中身が異なるものがあります。 大きな違いが生まれているのは、display_rows()メソッドです。このメソッドについて見ていきましょう。
display_row()メソッドの比較[^3]
・WP_List_Table
1 2 3 4 5 |
public function display_rows() { foreach ( $this->items as $item ) { $this->single_row( $item ); } } |
・WP_Posts_list_Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public function display_rows( $posts = array(), $level = 0 ) { global $wp_query, $per_page; if ( empty( $posts ) ) { $posts = $wp_query->posts; } add_filter( 'the_title', 'esc_html' ); if ( $this->hierarchical_display ) { $this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page ); } else { $this->_display_rows( $posts, $level ); } } private function _display_rows( $posts, $level = 0 ) { $post_type = $this->screen->post_type; $post_ids = array(); foreach ( $posts as $a_post ) { $post_ids[] = $a_post->ID; } if ( post_type_supports( $post_type, 'comments' ) ) { $this->comment_pending_count = get_pending_comments_num( $post_ids ); } update_post_author_caches( $posts ); foreach ( $posts as $post ) { $this->single_row( $post, $level ); } } |
コードを見れば、display_rows()メソッドの中身が大きく変わっていることがわかります。WP_List_Tableでは、single_row()メソッドをforeachで実行しているだけですが、WP_Posts_List_Tableクラスでは、_display_ro()というメソッドが呼び出され、さらにその中でsingle_row()メソッドが呼び出されています。引数を見ればわかりますが、このメソッドも中身が変わっています。
single_row()メソッドの比較
・WP_List_Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
public function single_row( $item ) { echo '<tr>'; $this->single_row_columns( $item ); echo '</tr>'; } protected function single_row_columns( $item ) { list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { $classes = "$column_name column-$column_name"; if ( $primary === $column_name ) { $classes .= ' has-row-actions column-primary'; } if ( in_array( $column_name, $hidden, true ) ) { $classes .= ' hidden'; } /* * Comments column uses HTML in the display name with screen reader text. * Strip tags to get closer to a user-friendly string. */ $data = 'data-colname="' . esc_attr( wp_strip_all_tags( $column_display_name ) ) . '"'; $attributes = "class='$classes' $data"; if ( 'cb' === $column_name ) { echo '<th scope="row" class="check-column">'; echo $this->column_cb( $item ); echo '</th>'; } elseif ( method_exists( $this, '_column_' . $column_name ) ) { echo call_user_func( array( $this, '_column_' . $column_name ), $item, $classes, $data, $primary ); } elseif ( method_exists( $this, 'column_' . $column_name ) ) { echo "<td $attributes>"; echo call_user_func( array( $this, 'column_' . $column_name ), $item ); echo $this->handle_row_actions( $item, $column_name, $primary ); echo '</td>'; } else { echo "<td $attributes>"; echo $this->column_default( $item, $column_name ); echo $this->handle_row_actions( $item, $column_name, $primary ); echo '</td>'; } } } |
・WP_Posts_list_Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public function single_row( $post, $level = 0 ) { $global_post = get_post(); $post = get_post( $post ); $this->current_level = $level; $GLOBALS['post'] = $post; setup_postdata( $post ); $classes = 'iedit author-' . ( get_current_user_id() === (int) $post->post_author ? 'self' : 'other' ); $lock_holder = wp_check_post_lock( $post->ID ); if ( $lock_holder ) { $classes .= ' wp-locked'; } if ( $post->post_parent ) { $count = count( get_post_ancestors( $post->ID ) ); $classes .= ' level-' . $count; } else { $classes .= ' level-0'; } ?> <tr id="post-<?php echo $post->ID; ?>" class="<?php echo implode( ' ', get_post_class( $classes, $post->ID ) ); ?>"> <?php $this->single_row_columns( $post ); ?> </tr> <?php $GLOBALS['post'] = $global_post; } |
WP_List_Tableでは、$itemに入った値を引数にしてsingle_row_columns()メソッドを実行し、一覧ページを作成していますが、WP_Posts_List_Tableでは、get_post()メソッドで投稿を取得し、それを引数にしてsingle_row_columns()メソッドを実行しています。single_row_columns()メソッドはWP_List_Tableクラスのものが継承されています。
投稿一覧ページを編集する
投稿一覧ページに使用されているクラスについて説明したので、次はページを編集して見ましょう。投稿一覧ページにはWP_Post_List_Tableクラスが既にあるので、新しくクラスを定義する必要はありません。 ページの編集には、フィルターフックを使用します。今回は抜粋を項目に追加しましょう。 以下のコードをfunctions.phpに記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function add_post_columns( $columns ) { $add_columns = array( 'excerpt' => '抜粋'); $columns = array_merge( $columns , $add_columns); return $columns; } add_filter('manage_posts_columns' , 'add_post_columns'); function add_post_custom_columns ( $columns, $postid ) { if ($columns === 'excerpt') { echo get_the_excerpt( $postid ); } } add_action( 'manage_posts_custom_column', add_post_custom_columns(...),10,2); |
すると、このように項目が追加されます。
WP_List_Tableを使用してテーブルを作成する[^4]
次に、オリジナルのテーブルを作成してみます。 今回は、投稿、固定ページ、カスタム投稿が全て表示される一覧リストを作っていきます。
手順1 WP_List_Tableを継承・拡張
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
class WP_All_Posts_List_Table extends WP_List_Table { public function __construct() { parent::__construct(); } private function set_posts() { global $wp_post_types; $all_posts = []; foreach ($wp_post_types as $post_type) { $posts = get_posts(array('post_type' => $post_type->name)); foreach($posts as $post) { $obj = new stdClass(); $obj->id = $post->ID; $obj->title = $post->post_title; $obj->post_type = $post_type->name; array_push($all_posts, $obj); } } return $all_posts; } public function prepare_items() { $columns= $this->get_columns(); $hidden= array(); $sortable= array(); $this->_column_headers= array($columns, $hidden, $sortable); $this->items = $this->set_posts(); } public function get_columns() { return array( 'cb' => 'checkbox', 'id' => 'id', 'title' => 'title', 'post_type' => '投稿タイプ' ); } public function single_row($item) { list($columns, $hidden, $sortable, $primary) = $this->get_column_info(); $id = $item->id; echo '<tr>'; printf('<td><input type="checkbox" name="checked[]" value="%d" /></td>', $id); printf('<td>%d</td>' ,$id); printf('<td>%s</td>', esc_html($item->title)); printf('<td>%s</td>', esc_html($item->post_type)); echo '</tr>'; } } |
コードの説明をしていきます。 class WP_All_Posts_List_Table extends WP_List_Tableは、WP_List_Tableクラスを継承したWP_All_List_Tableクラスを宣言しています。これで、WP_List_Tableクラスのメソッドがこのクラスで使えるようになります。 そして初めに__construct()を親から引き継ぎます。__construct()は、クラスのインスタンスが生成されたときに実行される関数です。
次にset_posts()は、このクラスオリジナルのメソッドで、テーブルに表示する情報を取得するために定義しました。 中身としては、$wp_post_typesで全ての投稿タイプを配列で取得し、foreachのなかでget_posts()で投稿を取得、画面に表示したいid、title、post_typeのプロパティが入ったオブジェクトを生成しまとまりを配列にして返す、という形になっています。
残りのメソッドは、WP_List_Tableクラスのメソッドをオーバーライドしています。オーバライドしたメソッドについて説明します。 prepare_items()は、itemsプロパティを定義するメソッドです。なので、先程のset_posts()をitemsに入れています。また、$columnsなどの変数の定義もここで行います。 get_columns()は、表示するテーブルのカラムの内容を決めます。このメソッドは、元々はdie()を返すメソッドなので、必ずオーバーライドする必要があります。今回はid、title、post_typeを表示するため、この3つを配列に入れました。 single_row()の変更は、今回はWordPressのオブジェクトから値を取り出すわけではないため、変更しました。中身としては通常のものとあまり変わりませんが、取り出すプロパティを自分で定義したオブジェクトのものに変更しています。
これでクラスの定義は完了しました。管理画面に表示してみましょう。
手順2 管理画面に表示
管理画面に表示するページを作成するために、add_menu_page()でページを追加しましょう。
1 2 3 4 5 6 7 8 9 10 11 |
function add_custom_menu() { add_menu_page( '投稿タイプ一覧画面', 'すべての投稿', 'manage_options', 'all_post', 'create_custom_menu_content', 'dashicons-menu-alt3', 3 ); }; |
これでページが追加されました。次に、ページを表示した際呼び出される関数として引数にセットしたcreate_custom_menu_content()を定義します。
1 2 3 4 5 6 7 |
function create_custom_menu_content() { $list_table = new WP_All_Posts_List_Table(); $list_table->prepare_items(); $list_table->display(); }; add_action('admin_menu',add_custom_menu(...), 9); |
edit.phpでテーブルを作成しているときと同じように、クラスのインスタンスを作成し、prepare_items()でitemをセットして、display()でテーブルを作成します。
これで管理画面にテーブルが表示されるはずです。管理画面を見て見ましょう。
まとめ
- テーブルを表示する際は、WP_Posts_List_Tableクラスや、WP_Media_List_Tableクラスなど、WP_List_Tableクラスの拡張クラスが使用されている。
- 投稿一覧のテーブルを編集する際にはmanage_posts_columnsフィルターフックをfuntions.phpに記述する。
- 自分でテーブルを作成する場合は、WP_List_Table クラスの拡張クラスを作成し、メソッドをオーバーライドする。
参考記事
- WP_List_Table
- [WP_Posts_List_Table] (https://developer.wordpress.org/reference/classes/wp_posts_list_table/)
- class-wp-list-table.php,line16-1874
- custom_table-list-columns
WordPressサイト制作・カスタマイズなら「wp.make」にお任せ!
WordPressでのサイト制作やリニューアルを検討する時、以下のようなお悩みはありませんか?
- WordPressに詳しい制作会社に依頼したいが、どこがいいかわからない…
- セキュリティ対策をしっかりしたいが、社内にノウハウがないのでプロに任せたい…
- WordPressに最適なサーバーの選定や構築から依頼したい…
- SEO対策や高速化も考慮したサイト構築を行なってほしい…
- 制作後の保守・運用についてもサポートしてほしい…
- 今のサイトを簡単に運用できるようにしてほしい…
「wp.make」は、WordPressのプロフェッショナル集団によるWordPressサイト制作・カスタマイズサービスです。
サイトの制作だけでなく、WordPressに最適なサーバーの選定や構築といったインフラ面の支援から、SEO対策や表示スピードの高速化、高度なセキュリティ対策や制作後の保守・運用サポートまで、WordPressに関わることならあらゆるお悩みを解消いたします。
既存のお客さまからも
「コミュニケーションが取りやすく、クオリティが高い」
「WordPressのプロとして信頼感がある」
と大変ご好評をいただいています。
WordPressサイトの制作・カスタマイズをご検討されているなら、ぜひ以下からお気軽にご相談ください。
WordPress開発・カスタマイズなら 『wp.make』
全案件WordPressのみ!
株式会社e2eの『wp.make』はWordPress専門のWeb制作サービスです。
WordPress案件だけを扱っているから、技術・ノウハウ・対応力が圧倒的!
【WordPressサイト制作でよくあるお悩み】
・運用シーンが想定されておらず、更新しづらかった…
・打ち合わせで専門用語が多くてわかりづらい…
・制作後の保守には対応してくれなかった…
こんな事態になる前に、ぜひ一度、ご相談ください!
WordPressサイトを作るなら、一番WordPressに詳しいところへ!