web-dev-qa-db-ja.com

WPクエリー順によるメタキーの自然なソート?

私はこのコードを持っています:

$args = array(
    'posts_per_page' => -1,
    'post_type' => 'product',
    'meta_key'   => 'custom key',
    'orderby'    => 'meta_value',
    'order'      => 'ASC',        
    'no_found_rows' => true,
    'cache_results' => false,
    'include_children' => false,
    'tax_query' => array(
        array(
            'taxonomy' => $taxonomy,
            'field' => 'id',
            'terms' => array($cat_id)
        )
    )
 );  

$loop = new WP_Query($args);    

カスタムキーが似ているとき

FA3
FA1
FA10

wp query orderbyパラメータはこれを以下のようにソートします。

FA1
FA10
FA3

nsort-algoritmが欲しい時は

FA1
FA3
FA10

WP_Queryでこれを達成する方法はありますか? (または、配列を作成し、その配列をnsort()でソートする唯一のオプションです。)

いいえ、まっすぐなWP_Queryとしてではありません。これはいくつかの要因によるものですが、主な要因は、mySQLが英数字列に対して自然なソートを行わないことです。

WordPressはorderbyパラメータに "meta_value_num"をサポートしています。これはソートを実行するために値をnumericにキャストするようにします。と数字、あなたはそれを使用することはできません。

posts_orderbyにフィルタを追加して、orderby句を直接書き換えて、好きなようにすることができます。データが常に "FA"で始まる場合は、フィルタに次のようなものを返させることができます。

LENGTH(meta_value) ASC, meta_value ASC

それは最初に長さによって、次に値によってソートします。短いアイテムが最初に来て、あなたに半自然な種類を与えます。

7
Otto

誰かがこれに遭遇した場合、私はあなたに解決策を与えるつもりです、それは「偽の自然なソート」(Ottoのおかげで)を使用します、しかしそれは複数のカスタムフィールドによるソートも持っています。

function orderbyreplace($orderby ) {
    global $wpdb;
    $new = str_replace($wpdb->prefix.'postmeta.meta_value ASC', 'LENGTH(mt1.meta_value) ASC, mt1.meta_value ASC, mt2.meta_value ASC', $orderby); 
    return $new;
}

function get_posts_by_tax_cat($taxonomy, $parent_cat_id) {
    $args = array(
        'posts_per_page' => -1, 
        'post_type' => 'product',
        'orderby' => 'meta_value',
        'order' => 'ASC',
        'meta_key' => 'flansoppning',     
        'meta_query' => array(
            array(
                'key' => 'flansoppning',
                'value' => '',
                'compare' => 'LIKE'
        ),
        array(
                'key' => 'gangstorlek_mm',
                'value' => '',
                'compare' => 'LIKE'
        )
    ),
    'no_found_rows' => true,
    'cache_results' => false,
    'include_children' => false,
    'tax_query' => array(
        array(
            'taxonomy' => $taxonomy,
            'field' => 'id',
            'terms' => array($parent_cat_id)
        )
    )
  );

//Filter makes it possible to sort on flansoppning (length() gives natural sort) first and then gangstorlek_mm
add_filter('posts_orderby','orderbyreplace');
$loop = new WP_Query( $args );
remove_filter('posts_orderby','orderbyreplace');

$posts = $loop->posts;

if(!empty($posts)) {
        return $posts;
}
return array();
}

Ottoの答えを補完するために、製品のpost_typeのみのクエリを変更する必要がある場合は、次の手順を試してください。

add_filter( 'posts_orderby', 'modify_posts_orderby', 10, 2 );
function modify_posts_orderby( $orderby_statement, $wp_query ) {
    // do not modify queries in the admin
    if( is_admin() ) { 
        return $orderby_statement;
    }

    // only modify queries for 'product' post type
    if( $wp_query->get( 'post_type' ) === 'product' ) {
        $orderby_statement = "LENGTH(meta_value) DESC, meta_value DESC";
    }
    return $orderby_statement;
}
0
Marcos Nakamine