投稿一覧の追加列にソート機能をつける


列の追加方法は 管理画面の投稿一覧に列を追加する にて解説しています。

  1. 投稿一覧に列を追加する
  2. 投稿一覧に絞り込みを追加する
  3. 投稿一覧の追加列にソート機能をつける

タイトルはデフォルトでソート可能ですが、著者列は独自に追加した列なのでソートができません。ここでは ▲ マークなど表示して、並び替えて表示ができるようにします。

ジャンルはタクソノミーのため、簡単に並び替え表示する方法が WordPress コアでは提供されていません。

投稿タイプの仕様は下記の通り

  • 書籍 book 投稿タイプ
  • written_byカスタムフィールド、表示名「著者」
  • genre タクソノミー、表示ラベル「ジャンル」

使用するフック

既存ソートの動作をみる

タイトルの横には、ソートのための▲マークが既に表示されるのでソートして表示させてみます。

タイトル順に昇順でソート表示されました。この時、URLにパラメターが追加されています。

追加されるパラメターは

  • orderby=title&order=asc タイトル昇順でソート表示されているとき
  • orderby=title&order=desc タイトル降順でソート表示されているとき

ソート可能な列に登録

スクリーン ID について

manage_{$this->screen->id}_sortable_columns フックを使って「著者列」を加えます。そのためには、スクリーンIDを特定する必要があります。

スクリーン ID は管理画面ごとに WordPress コアにより付与されます。get_current_screen 関数などで取得できます。

  • 通常投稿の一覧画面:edit-post
  • 書籍投稿の一覧画面:edit-book

よって、書籍投稿タイプの一覧に適用するためのフック名は manage_edit-book_sortable_columns

ソート可能な列に追加

無名関数を使います。フックの引数 $sortable_columns 配列に、列名をキーとしてソート名を追加。

一旦、sort_written_byというソート名として、著者列でのソートを追加してみます。

add_filter(
	'manage_edit-book_sortable_columns',
	function ( $columns ){
		$columns['written_by'] = 'sort_written_by';
		return $columns;
	},
	10,
	1
);

▲ マーククリックで、画面が切り替わります。一見、並び変わったように見えますが、単にデフォルトから逆順に並んだだけです。著者順には並んでいません。

ここでは URL に &orderby=sort_written_by&order=asc というパラメターが追加されました。

$sortable_columns 配列に追加した sort_written_byorderby パラメターの値としてセットされます。すなわち、著者列 written_by の ▲ マークでソートすると sort_written_by というソートモードに画面が切り替わります。

分かりやすくするために冗長にしていた値を修正して、最終的にはこのようなコードとします。

add_filter(
	'manage_edit-book_sortable_columns',
	function ( $columns ){
		$columns['written_by'] = 'written_by';
		return $columns;
	},
	10,
	1
);

次に、実際に著者順で並ぶようにクエリーを調整します。

クエリーを調整

まず、管理画面の書籍投稿の一覧画面かどうかの判定を実装します。

add_action(
	'pre_get_posts',
	function ( $query ) {
		if ( ! is_admin()
		|| ! $query->is_main_query()
		|| ! isset( $query->query['post_type'] )
		|| ! isset( $query->query['orderby'] ) ) {
			return;
		}

		if ( 'book' !== $query->query['post_type'] ) {
			return;
		}
		
		// このセクションは書籍投稿の一覧画面で、ソートモードの時にのみ実行される.

		return;
	},
);

こういう時は、自分は早期リターン( early return ) を使って実装しています。

ここまで判定を増やさなくても、 is_admin() $query->is_main_query() と投稿タイプ判定の3つでいいような気もします。

次にカスタムフィールドでソートするための $query の調整を実装します。
検索すると、set( 'meta_key', value )set( 'orderby', value ) でできる情報が出てきます。

$queryWP_Query オブジェクトなので、公式リファレンスも見ておきます。
WP_Query – Class | Developer.WordPress.org

下記のコード例がみつかりました。

Display posts with ‘Product’ type ordered by ‘Price’ custom field:

$args = array(
  'post_type' => 'product',
  'orderby' => 'meta_value_num',
  'meta_key' => 'price',
);
$query = new WP_Query( $args );

orderby で比較方法を指定、meta_key でソートの基準にするカスタムフィールドを指定すればよさそうです。

よって、クエリーの調整は

$query->set( 'meta_key', 'written_by' );
$query->set( 'orderby', 'meta_value' );

URLパラメターが&orderby=written_by の時に、written_by フィールド基準にソートして欲しいので、さらに条件判定を追加

if( 'written_by' === $query->query['orderby'] )

pre_get_query フックで実行する最終的なコードはこうなります。

add_action(
	'pre_get_posts',
	function ( $query ) {
		if ( ! is_admin()
		|| ! $query->is_main_query()
		|| ! isset( $query->query['post_type'] )
		|| ! isset( $query->query['orderby'] ) ) {
			return;
		}

		if ( 'book' !== $query->query['post_type'] ) {
			return;
		}
		
		if( 'written_by' === $query->query['orderby'] ){
			$query->set( 'meta_key', 'written_by' );
			$query->set( 'orderby', 'meta_value' );
		}

		return;
	},
);

動作確認

著者順でソート表示できました。漢字の著者名の場合、シフトJIS → UTF でコードが若い順になりますので、綺麗な50音にはなりませんが。

最終的なコード

add_filter(
	'manage_book_posts_columns',
	function ( $columns ){
		$written_by_column = array(
			"written_by" => "著者"
		);

		$new_columns = array_slice( $columns, 0, 1 )
						+ $written_by_column
						+ array_slice( $columns, 1, count( $columns ) - 1 );

		return $new_columns;
	},
	10,
	1
);

add_action(
	'manage_book_posts_custom_column',
	function ( $column_name, $id ) {
		if ( 'written_by' === $column_name ) {
			echo get_post_meta( $id, 'written_by', true );
		}
	},
	10,
	2
);

add_filter(
	'manage_edit-book_sortable_columns',
	function ( $columns ){
		$columns['written_by']='written_by';
		return $columns;
	},
	10,
	1
);

add_action(
	'pre_get_posts',
	function ( $query ) {
		if ( ! is_admin()
		|| ! $query->is_main_query()
		|| ! isset( $query->query['post_type'] )
		|| ! isset( $query->query['orderby'] ) ) {
			return;
		}

		if ( 'book' !== $query->query['post_type'] ) {
			return;
		}
		
		if( 'written_by' === $query->query['orderby'] ){
			$query->set( 'meta_key', 'written_by' );
			$query->set( 'orderby', 'meta_value' );
		}

		return;
	},
);

add_action(
	'admin_print_styles',
	function () {
		echo '<style>
.column-written_by {
width: 10rem;
}
</style>' . PHP_EOL;
	}
);

カテゴリー:

最終更新: