web-dev-qa-db-ja.com

分類フィルタを使用してカスタム投稿タイプを照会し、投稿タイプアーカイブページを表示する方法

私はこのフックを使って私自身の分類法でJigoshopのメインクエリーをフィルタリングしています( 私がフックしているJigoshopクエリーを担当するファイル、JigoshopはWP 'リクエストにフックします'フィルタ ):

add_filter( 'loop_shop_tax_query', 'my_loop_shop_tax_query', 11 );
function loop_shop_tax_query( $request )
{
    $region = 'dublin';
    if ( ! empty( $region ) ) {
        $request[] = array(
            'taxonomy'  => 'product_region',
            'field'     => 'slug',
            'terms'     => $region,
            'operator'  => 'IN',
        );
    }

    return $request;
}

このようにしてすべてのJigoshopクエリをフィルタリングします(すべての製品表示、カテゴリ表示および検索表示)。これは意図したとおりに動作していますが、htmlヘッドのwp_title()がエラーの原因となっています。

Notice: Undefined property: stdClass::$labels in /var/www/wp/wp-includes/general-template.php on line 658

Notice: Trying to get property of non-object in /var/www/wp/wp-includes/general-template.php on line 658

General-template.phpでこれを追跡し、is_post_type_archive()もtrueを返していますが、get_tax()はtrueを返しています。 get_queried_object()は私のタクソノミーオブジェクト(通常Jigoshop製品のカスタム投稿タイプオブジェクト)を返しています。

Jigoshop製品のカスタム投稿タイプオブジェクトを返すにはget_queried_object()が必要で、get_tax()はfalseを返す必要があります。分類を使用して投稿をフィルタリングしたいのですが、投稿タイプのアーカイブを表示し続けたいです。

リクエストが 'request'フィルタのためにWPに送り返される直前に、それはこのように見えます:

Array ( [post_type] => product [post_status] => publish [posts_per_page] => 12 [orderby] => post_date [order] => asc [tax_query] => Array ( [relation] => AND [0] => Array ( [taxonomy] => product_region [field] => slug [terms] => dublin [operator] => IN ) ) [meta_query] => Array ( [0] => Array ( [key] => visibility [value] => Array ( [0] => visible [1] => catalog ) [compare] => IN ) ) [post__in] => Array ( [0] => 293 [1] => 291 [2] => 289 [3] => 18 [4] => 0 ) )

私はこれがあまり具体的ではなく、理にかなっていることを願っています、私は本当にここで私のウィットの終わりにいます、どんな助けでも大いに感謝されるでしょう。

1
wickedbroccoli

最も単純な方法は、誠実に言うと、wp_titleにフックして変更することです。警告は表示されますが、運用環境では表示されないことに注意してください(サーバーを設定したため)。

以下は一種のハックな解決策です。

get_queried_object...を見れば.

<?php
function get_queried_object() {
    global $wp_query;
    return $wp_query->get_queried_object();
}

WP_Query::get_queried_objectのまわりの薄いラッパーですので、それを見てみましょう。

<?php
function get_queried_object() {
    if ( isset($this->queried_object) )
        return $this->queried_object;

    $this->queried_object = null;
    $this->queried_object_id = 0;

    if ( $this->is_category || $this->is_tag || $this->is_tax ) {
        $tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );

        $query = reset( $tax_query_in_and );

        if ( 'term_id' == $query['field'] )
            $term = get_term( reset( $query['terms'] ), $query['taxonomy'] );
        elseif ( $query['terms'] )
            $term = get_term_by( $query['field'], reset( $query['terms'] ), $query['taxonomy'] );

        if ( ! empty( $term ) && ! is_wp_error( $term ) )  {
            $this->queried_object = $term;
            $this->queried_object_id = (int) $term->term_id;

            if ( $this->is_category )
                _make_cat_compat( $this->queried_object );
        }
    } elseif ( $this->is_post_type_archive ) {
        $this->queried_object = get_post_type_object( $this->get('post_type') );
    } elseif ( $this->is_posts_page ) {
        $page_for_posts = get_option('page_for_posts');
        $this->queried_object = get_post( $page_for_posts );
        $this->queried_object_id = (int) $this->queried_object->ID;
    } elseif ( $this->is_singular && !is_null($this->post) ) {
        $this->queried_object = $this->post;
        $this->queried_object_id = (int) $this->post->ID;
    } elseif ( $this->is_author ) {
        $this->queried_object_id = (int) $this->get('author');
        $this->queried_object = get_userdata( $this->queried_object_id );
    }

    return $this->queried_object;
}

お分かりのように、WordPressはたくさんのものをチェックして、これがどんな種類のクエリなのか、どこに設定されているのかを確かめます。最初のチェックは、これがカテゴリ、タグ、または分類アーカイブのいずれであるかを確認することです。それが成功するので、投稿タイプアーカイブオブジェクトは決して設定されません。

本当に奇妙なのは、is_post_type_archiveis_taxの両方がtrueを返す理由です。 WP_Query::parse_queryが機能する方法のために、アーカイブはポストタイプアーカイブと分類アーカイブの両方になることが可能です。

とにかく、WP_Query::$queried_objectはパブリックプロパティなので、wp_titleが起動して置き換えられる前にどこかにフックするだけです。 template_redirectは動作します。

これは非常にハックですが、警告を防ぐことができるようなpre_wp_titleフィルタなどはありません。以下のテストされていない例WPコアが今後のリリースで$queried_objectを非公開または保護プロパティにすることを決定した場合、これは機能しないことに注意してください。それはまたあなたのサイトの他の部分に悪影響を及ぼす可能性があります。

<?php
add_action('template_redirect', 'wpse87222_change_object');
function wpse87222_change_object()
{
    global $wp_the_query;

    // check for post type archive
    if (is_post_type_archive('product')) {
        $wp_the_query->queried_object = get_post_type_object('product');
    }
}
2
chrisguitarguy