私はカスタム投稿タイプの並べ替え機能を構築しています、そして私は "Featured"投稿のカスタムメタ値を持っています。この値はチェックボックスをチェックすると設定され、そうでなければ設定されません。
デフォルトのorderby=meta_value
をmeta_key=featured
と一緒に使用すると、メタキーを持つ投稿のみが画面に表示されます。そうでなければ、彼らも現れません。
設定されていない場合は表示されますが、最後に表示されます。代わりにmeta_query
を使用する必要があると思いますが、それを機能させることもできませんでした。
WP_Query引数で空、偽、または存在しないメタキーを許可するにはどうすればよいですか。
私のコードは以下の通りです。これはダッシュボードで列をソートするためのものであるため、デフォルトのWP Query argsを変更しています。
function featured_sortable_order( $vars ) {
if ( isset($vars['orderby']) && $vars['orderby'] == 'featured' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'featured',
'orderby' => 'meta_value',
'order' => isset($vars['order']) ? $vars['order'] : 'asc',
) );
}
return $vars;
}
add_filter( 'request', 'featured_sortable_order' );
問題は、メタ値を注文するためには、WordPressがクエリ内の'meta_key'
を何かに設定する必要があることです。 'meta_key'
を何かに設定すると、WordPressは次のように追加します。
AND ( wp_postmeta.meta_key = 'the_meta_key' )
WHERE
SQL句へ。そして何かのような
INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
join
節へ。そのため、queryはそのメタクエリを持つ投稿のみを返します。
バックエンドで作業していて、コラムを表示するために投稿ごとにget_post_meta( $postid, 'featured', true)
を呼び出しても、get meta functionのWordPressキャッシュのおかげで2回呼び出すことはパフォーマンス上の大きな問題ではありません。
そのため、(メタキーにフィルタを追加せずに)すべての投稿を取得してから、'posts_results'
フックを使用して投稿をフィルタリングし、「注目の」メタキーを見て投稿を注文するという考えです。
使用した直後にフィルタを削除します。
add_filter( 'posts_results', 'order_by_featured', PHP_INT_MAX, 2 );
function order_by_featured ( $posts, $query ) {
// run only on admin, on main query and only if 'orderby' is featured
if ( is_admin() && $query->is_main_query() && $query->get('orderby') === 'featured' ) {
// run once
remove_filter( current_filter(), __FUNCTION__, PHP_INT_MAX, 2 );
$nonfeatured = array();
$featured = array();
foreach ( $posts as $post ) {
if ( get_post_meta( $post->ID, 'featured', TRUE ) ) {
$featured[] = $post;
} else {
$nonfeatured[] = $post;
}
}
$order = strtoupper( $query->get('order') ) === 'ASC' ? 'DESC' : 'ASC';
// if order is ASC put featured at top, otherwise put featured at bottm
$posts = ( $order === 'ASC' )
? array_merge( $nonfeatured, $featured )
: array_merge( $featured, $nonfeatured );
}
return $posts;
}
さらに、クエリに順序が設定されていない場合にデフォルトの順序として'pre_get_post'
を使用するように、'ASC'
にフィルタを追加します。
add_action( 'pre_get_posts', function( $query ) {
// if no order is set set order to ASC
if (
is_admin() && $query->is_main_query()
&& $query->get('orderby') === 'featured'
&& $query->get('order') === ''
) {
$query->set( 'order', 'ASC' );
}
});