web-dev-qa-db-ja.com

カスタムフィールドで投稿を注文し、カスタムフィールドが空の場合は残りの投稿を返す

カスタムフィールドにアーカイブページが数値順に並んでいます。これにより、順序付けされた投稿が正しく返されますが、カスタムフィールドがない投稿は表示されません。

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; 
query_posts("paged=$paged&cat=7&posts_per_page=24&meta_key=custom_order&orderby=meta_value_num&order=ASC");

注文された投稿を正しく返し、その後にカスタムフィールドの値が関連付けられていない投稿を正しく返すための最良の方法は何ですか?

編集 :手の込んだ - 最終的に達成したいのは、特定の投稿が最初に表示され、次に残りの部分が表示されるカテゴリアーカイブページです。スティッキーな投稿とほとんど同じですが、特定のカテゴリのアーカイブ専用です。

編集2 :私はジェシカの提案を試みています、そして私たちはほとんどそこにいると思います。

問題は、order=ASCに設定した場合、カスタムフィールドが埋められているすべての投稿が、値が関連付けられていない投稿の後に表示されることです。 order=DESCを設定すると、カスタムフィールド値を持つ投稿が最初に返されますが、その逆になります。つまり、4、3、2、1、そして残りの投稿には値が関連付けられていません。 custom_orderフィールドに1、2、3、4、そして残りの投稿が表示されないように、順序を修正するにはどうすればよいですか。

私のfunctions.phpに以下を追加しました。

function wpse_55791_custom_order($clauses)
{
    global $wp_query;

    // check for order by custom_order
    if ($wp_query->get('meta_key') == 'custom_order' && $wp_query->get('orderby') == 'meta_value_num')
    {
        // change the inner join to a left outer join, 
        // and change the where so it is applied to the join, not the results of the query
        $clauses['join'] = str_replace('INNER JOIN', 'LEFT OUTER JOIN', $clauses['join']).$clauses['where'];
        $clauses['where'] = '';
    }
    return $clauses;
}
add_filter('get_meta_sql', 'wpse_55791_custom_order', 10, 1);
function wpse_55791_custom_orderby($orderby)
{
    global $wp_query;

    // check for order by custom_order
    if ($wp_query->get('meta_key') == 'custom_order' && $wp_query->get('orderby') == 'meta_value_num')
    {
        $orderby = "{$wpdb->postmeta}.meta_value='', ".$orderby;
    }
    return $orderby;
}
add_filter('posts_orderby', 'wpse_55791_custom_orderby', 10, 1);
2
Ryan

Meta_keyを指定すると、query_posts()はwp_postsテーブルとwp_postmetaテーブルの間でINNER JOINを行います。つまり、指定したキーのメタ値を持たない投稿は、そのクエリで返されることは決してありません。

必要なことをするには、質問で投稿したのと同じクエリを使用しますが、orderby=meta_valueorderby=meta_value_numに変更します。その後、 'get_meta_sql'をフィルタリングして、結合がすべての投稿を返すようにすることができます。 functions.phpに以下を追加してください。

<?php
function wpse_55791_custom_order($clauses)
{
    global $wp_query;

    // check for order by custom_order
    if ($wp_query->get('meta_key') == 'custom_order' && $wp_query->get('orderby') == 'meta_value_num')
    {
        // change the inner join to a left join, 
        // and change the where so it is applied to the join, not the results of the query
        $clauses['join'] = str_replace('INNER JOIN', 'LEFT JOIN', $clauses['join']).$clauses['where'];
        $clauses['where'] = '';
    }
    return $clauses;
}
add_filter('get_meta_sql', 'wpse_55791_custom_order', 10, 1);
?>

編集:順序を修正するには、上記と一緒にこれを追加してみてください:

<?php
function wpse_55791_custom_orderby($orderby)
{
    global $wp_query, $wpdb;

    // check for order by custom_order
    if ($wp_query->get('meta_key') == 'custom_order' && $wp_query->get('orderby') == 'meta_value_num')
    {
        $orderby = "{$wpdb->postmeta}.meta_value='', ".$orderby;
    }
    return $orderby;
}
add_filter('posts_orderby', 'wpse_55791_custom_orderby', 10, 1);
?>

EDIT TWO - 2ループ:

これが私のやり方です。

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; 
$ordered_posts = new WP_Query(array(
    'paged' => $paged,
    'cat' => 7,
    'posts_per_page' => 24,
    'meta_key' => 'custom_order',
    'orderby' => 'meta_value_num',
    'order' => 'ASC',
));

$unordered = new WP_Query(array(
    'cat' => 7,
    'paged' => $paged,
    'posts_per_page' => 24 - $ordered_posts->post_count,
));

if ($ordered_posts->have_posts()) :
    while ($ordered_posts->have_posts()) : $ordered_posts->the_post();
    // loop 1
    endwhile;
endif;

if ($unordered_posts->have_posts()) :
    while ($unordered_posts->have_posts()) : $unordered_posts->the_post();
    // loop 2
    endwhile;
endif;

24個を超える順序付き投稿があると思われる場合は、順序付けされていない投稿に対してpaged変数が間違っていることに注意してください。これまでに表示された順序付き/順序なし投稿の数を追跡するためにグローバル変数を設定し、それを使用してタイプごとに個別の$paged値を計算する必要があるかもしれません。

4
jessica

投稿IDを配列に入れて、それらのIDを除くすべての投稿を照会することができます。

$post_ids = array();
foreach( $wp_query->posts as $post ):
    $post_ids[] = $post->ID;
endforeach;

$args = array(
    'posts_per_page' => -1,
    'post__not_in' => $post_ids
);
$remaining = new WP_Query( $args );
2
Milo

以下のように、配列を配列に使って、非常に簡単な方法でこれを解決しました。

$posts = get_posts(array(
                    'orderby' => array(
                        'meta_key' => 'meta_key', /* your meta key here */
                        'meta_value' => 'meta_value_num',
                        'order' => 'DESC',
                    )
            ));   

これで解決するはずです:)

1
luqita

これは、私がまったく気に入らなくても良い回避策です。これもまた、wordpressのクエリAPIの制限です。私は昔からmysqlでそれをするのが大好きでした.. WPをいじることは時々..

//get only ordered posts
$args = array(
    'post_type'=>'supporters',
    'order' => 'ASC',
    'orderby' => 'meta_value_num',
    'meta_key' => 'wpcf-sorting'
);
$cat_posts = new WP_Query($args);

//collect ordered post ids
$post_ids = array();
foreach( $cat_posts->posts as $post ):
    $post_ids[] = $post->ID;
endforeach;


//get only unordered posts
$args = array(
    'post_type'=>'supporters',
    'posts_per_page' => -1,
    'post__not_in' => $post_ids
);
$cat_posts_unordered = new WP_Query($args);


if ($cat_posts->have_posts() || $cat_posts_unordered->have_posts()) {   
    while ($cat_posts->have_posts()) {
        $cat_posts->the_post();

        get_template_part( 'content-supporters', get_post_format());
    }
    while ($cat_posts_unordered->have_posts()) {
        $cat_posts_unordered->the_post();

        get_template_part( 'content-supporters', get_post_format());
    }
}
0
mitchiru

簡単さの点で、そして私の解決策は管理者パネルのためのものであるので、それは効率に焦点を合わせていません。私がしたことはすべての投稿をロードしてからphpを使ってソートすることです。

function MY_PLUGIN_get_ordered_pages_by_cat_id($cat_id) {
    $all_pages = get_posts(
                array(
                    'post_type' => 'page',
                    'cat' => $cat_id,
                    'order' => 'ASC'
                )
            );

    $pages      = [];
    $page_len   = count($all_pages);
    foreach($all_pages as $page):
        $positon        = @get_post_meta($cat_id, '_page_position', true);
        $a_pos          = !empty($positon) ? $positon : $page_len++;
        $pages[$a_pos]  = $page;
    endforeach;
    sort($pages);
    return $pages;
}

多分それは誰かに役立ちます。 :)

0