web-dev-qa-db-ja.com

Pre_get_posts()アクション内の複数のorderbyパラメータ

@ Otto's response 私が複数のフィールドで並べ替えることについての質問に対して/ /を参照する、これが彼が言ったことです:

素朴なWP_Queryではできません。 posts_orderbyフィルタを使用して、独自の順序文字列を追加してください。

function my_order($orderby) { 
    global $wpdb; 
    return "{$wpdb->posts.post_author} ASC, {$wpdb->posts.post_date} DESC"; 
} 
add_filter( 'posts_orderby', 'my_order' ); 

$blah = new WP_Query(...); 

remove_filter( 'posts_orderby', 'my_order' ); 

- オットー

これは、WP_Queryへの新しい呼び出しで行われる方法のようです - > 2つのメタフィールドを持つpre_get_posts()アクションで、これと同じことをデフォルトのソート順でどのように実行するのでしょうか。

function mouldings_sort($query) {
    if ($query->is_main_query() && is_tax(array('wood_types','profile_categories','combination_categories'))) {

        $query->set('meta_key', '_mouldings_dimensions_height');
        $query->set('order', 'DESC');
        $query->set('orderby','meta_value_num');
    }

}
add_action('pre_get_posts','mouldings_sort');

私は以前、次のように単に別のメタフィールドを追加しようとしました。

$query->set('meta_key', array('_mouldings_dimensions_height', '_mouldings_dimension_width'));
$query->set('orderby','meta_value_num');

デフォルトのソートバックtitleは以下のようになります。

 $query->set('orderby','meta_value_num title');

しかしmeta_keyが配列を受け入れることができるようには見えず、私のtitleのフォールバックはこの問題に関するOttoの最初の回答に戻ります。任意の助けは大歓迎です。ありがとうございます。

3
Zach

実際に 2つのフィルタがあることを忘れないでください

// Add additional query args that are allowed by the API by default
pre_get_posts
// Modify the query herself
posts_clauses
// Inspect the resulting string - test this one in for e.g. phpMyAdmin
posts_request

ですから、pre_get_postsフィルタを使って達成できることはすべてそこで行われるべきです。残りはposts_clauses(または以前のより具体的なフィルタの1つ)を使用して変更する必要があります。

// Modify the original query parts
function wpse70214_pre_get_posts( $query )
{
    var_dump( $query );
    return $query;
}
add_filter( 'pre_get_posts', 'wpse70214_pre_get_posts' );

// Modify the resulting query string parts
function wpse70214_posts_clauses( $pieces )
{
    var_dump( $pieces );
    return $pieces;
}
add_filter( 'posts_clauses', 'wpse70214_posts_clauses' );

// Then check the result
function wpse70214_posts_request( $query_string )
{
    var_dump( $query_string );
    return $query_string;
}
add_action( 'posts_request', 'wpse70214_posts_request' );
2
kaiser

はい、Ottoが言ったように、カスタムのORDER BYフィルタなしでは二次のposts_orderby句を持つことはできません。あなたがla "pre_get_posts"に対してあなたのどんなクエリを知る必要があるなら、posts_orderbyにorderbyフィルタを追加し、pre_get_postsからそれを呼び出す関数を作成することができます。

/**
 * Posts orderby filter.  The filter will be added using pre_get_posts outside the class
 *  using the pre_get_posts action allows us to do checks for what page etc...
 * @return string, new MySQL ORDER BY clause
 */
function wpse_order_by() {
    global $wpdb;
    return $wpdb->prepare( "$wpdb->postmeta.meta_value+0 DESC, post_title DESC" );
}

/**
 * Pre get posts filter for adding secondary fall back ORDER BY clause to MySql query
 * @uses remove_filter(), This filter removes itself after it runs to prevent it from affecting  other queries on the same page.
 * @uses add_filter()
 * @param object|array $query the current $query object
 */
function wpse_post_order_pre( $query ) {
    if ($query->is_main_query() && is_tax(array('wood_types','profile_categories','combination_categories'))) {

    /** remove_filter() is used to prevent this affecting additional queries on the page */
    remove_filter( current_filter(), __FUNCTION__ );

    add_filter( 'posts_orderby', 'wpse_order_by' );
    }
}

add_action( 'pre_get_posts', 'wpse_post_order_pre' );
1
Chris_O