web-dev-qa-db-ja.com

分類用語に含まれていないすべてのカスタム投稿を検索から除外する

分類法が関連付けられたカスタム投稿があります。この分類法には1つの用語しかなく、投稿はそれに属しているかどうかにかかわらず、ブール式になっています。

検索結果に、分類法に属するカスタム投稿を表示し、分類に属さない投稿は表示しないようにします。これを達成するための2つの方法を考えましたが、どちらが最良であるかはわかりません。

  • 分類学用語に属するカスタム投稿のみを含める。
  • 分類用語に属さないすべてのカスタム投稿を除外します。

私は、次のコードを使って、自分が望むものと正反対のことをすることができました。

global $query_string;
$query_args = explode("&", $query_string);
$search_query = array();
foreach($query_args as $key => $string) {
    $query_split = explode("=", $string);
    $search_query[$query_split[0]] = urldecode($query_split[1]);
}

$custom_query = array();
$custom_query['tax_query'][] = array( 'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'), 'field' => 'slug', 'operator' => 'NOT IN' );
$args = array_merge( $wp_query->query, $custom_query );
query_posts( $args );

$search = new WP_Query($search_query);

これは、もちろん、期間に関係なくすべてのカスタム投稿を出力します。正反対のことをどのようにして達成できますか?

編集

私は私の問題をもう少し説明しようとします。例を使ってみましょう。

ユーザーがチェックボックスで選択できる「選択済み」および1つの「はい」と呼ばれる分類用語という分類法があるとします。 2つのチェックボックス(「はい」と「いいえ」)を使用する必要があると思いますが、当時はあまり意味がないと思いました。

ユーザーがWebサイトで何かを検索すると、すべてのページ、投稿、およびカスタム投稿が結果に表示されます。私が検索結果から削除したいのはカスタム分類で、分類用語「はい」と関連付けられていないだけで、残りはすべてそのままです。つまり、すべてのページ、投稿、および "はい"のカスタム投稿を出力したいのです。

どのように私はこれを達成することができますか?ありがとう。

UPDATE

これは私が持っていた考えです:私は2つの質問をして結果をマージすることができる方法はありますか?

  • カスタム投稿('exclude_from_search' => true)を除くすべての投稿とページを含む1つのクエリ。
  • 分類学用語($custom_query['tax_query'][] = array( 'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'), 'field' => 'slug', 'operator' => 'IN' );)に一致するカスタム投稿のみを含むその他のクエリ。

しかし、私が以下のようなものを使うならば:

$mergedposts = array_merge( $wp_query->query, $custom_query );
query_posts( $mergedposts );

カスタム投稿のみが表示されます。

私はSQLで直接問い合わせをすることができると思いますが、私はそれを使ったことがありません。それは私が将来学びたいことですが、私は自分のしていることを理解できないので、今のところこの種の問題を解決するのに良い方法とは思えません。

今のところ私の最良の選択は今までのところ新しい分類学用語を作成し、それと共にすべての「未分類」のカスタム投稿を分類することです。しかし、それらは数百なので、しばらく時間がかかります。

NEW UPDATE

カスタム投稿が分類法の特定の用語に属しているかどうかを検出する方法を見つけました。私は自分でこのようなものを作成するためのPHP知識を持っていないので、これは私がどこかで手に入れたコードの一部です。しかし、私は何が行われているのかを理解し、それを自分の状況に合わせました。

function is_selected( $selected, $_post = null ) {
    if ( empty( $selected ) )
        return false;

    if ( $_post )
        $_post = get_post( $_post );
    else
        $_post =& $GLOBALS['post'];

    if ( !$_post )
        return false;

    $r = is_object_in_term( $_post->ID, 'selected', $selected );

    if ( is_wp_error( $r ) )
        return false;

    return $r;
}

この関数は正しく機能しますが、ループ内で使用された場合のみです。しかし、検索クエリが作成された後にループを変更すると、ページ付けが台無しになり、見つかった結果の数が間違ってしまう可能性があります。

これが正しい方向へのステップであるかどうかはわかりませんが、少なくともそれはステップです。

3
Cthulhu

あなたの改訂された質問を読んだ後は、あなたが何をしようとしているのかを理解するのがより簡単でした。私の新しい解決策はそもそもあなたがやりたいことのように見えます:それはあなたのカスタムタイプであるがそれに関連する "yes"という用語を持たない全ての投稿を単に除外します:

$custom_query = array();
$custom_query['post_type'] = 'any';

// first, query all the posts of your custom type
// that don't have the "yes"-term:
$tmp_wp_query = new WP_Query(array(
    'posts_per_page' => -1,
    'fields' => 'ids',
    'post_type' => 'your-post-type',
    'tax_query' => array(array(
        'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'),
        'field' => 'slug', 'operator' => 'NOT IN'
    ))
));

if(!empty($tmp_wp_query->posts)) {
    // Exclude the "yes"-less posts from the actual post query
    $custom_query['post__not_in'] = $tmp_wp_query->posts;
}

// now proceed with your original code and execute the definitive query
$args = array_merge( $wp_query->query, $custom_query );
query_posts( $args );

$search = new WP_Query($search_query);

唯一の欠点は、実行するクエリが2つあることです。しかし、最初のクエリは比較的軽量なので、パフォーマンスの低下はそれほど大きくないはずです。

6
vstm