Sắp xếp theo giá trị meta nhưng bao gồm các bài đăng không có


37

Tôi đã sửa đổi tìm kiếm WP tích hợp bằng pre_get_postsbộ lọc, cho phép người dùng sắp xếp các bài đăng (bao gồm một loạt các loại bài đăng tùy chỉnh) theo các trường khác nhau.

Vấn đề tôi gặp phải là khi tôi bảo WP sắp xếp theo một giá trị meta, nó sẽ loại trừ tất cả các bài đăng không có giá trị meta đó được đặt. Điều này khiến số lượng kết quả thay đổi nếu bạn thay đổi cách sắp xếp từ nói "Giá" thành "Ngày" vì "Bài đăng" không được đặt "Giá" nhưng "Mục" thì có.

Đây không phải là điều tôi muốn, vì vậy tôi muốn biết liệu có cách nào để bao gồm TẤT CẢ các bài đăng hay không - ngay cả những bài viết thiếu giá trị meta mà tôi sắp xếp - và đặt bài viết không có giá trị cuối cùng.

Tôi biết cách sắp xếp trên nhiều lĩnh vực nhưng điều đó không có ích.

Cảm ơn

Có vẻ như tôi không phải là người duy nhất có câu hỏi này: Cách bao gồm các bài đăng cả có & không có meta_key nhất định trong các đối số cho wp_query? nhưng không có giải pháp ở đó.

Cập nhật

Tôi đã thử câu trả lời nhưng không chắc là tôi đã hiểu đúng chưa, đây là những gì tôi có ngay bây giờ:

<?php
function my_stuff ($qry) {
    $qry->set('meta_query', array(array(
        'key' => 'item_price', 
        'value' => '', 
        'compare' => 'NOT EXISTS'
    )));

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Giá trị meta là một số (nó được sử dụng để lưu trữ giá như tên cho thấy)

Cập nhật 2

Tôi đã nhận xét các công cụ đặt hàng và tất cả những gì tôi có bây giờ là:

<?php
$qry->set('meta_query', array(array(
    'key' => 'item_price', 
    'value' => '', 
    'compare' => 'NOT EXISTS'
)));

Với mã này, truy vấn dường như trả về tất cả các bài đăng không có item_pricekhóa và không có bài đăng nào có nó. IE vấn đề bây giờ đã đảo ngược.

Nếu tôi thêm vào mã thứ tự, tôi nhận được 0 kết quả.

Chỉnh sửa: ... ba năm sau ... : PI lại gặp vấn đề này. Tôi đã thử tất cả các câu trả lời được đưa ra và không có công việc. Không chắc chắn tại sao một số người dường như nghĩ rằng họ làm việc nhưng ít nhất họ không làm việc cho tôi.

Giải pháp tôi đã kết thúc là sử dụng save_postbộ lọc - đảm bảo tất cả các bài đăng đều có trường tùy chỉnh tôi muốn sắp xếp. Hơi khó chịu một chút là tôi phải làm điều đó, nhưng miễn là bạn làm sớm thì bạn sẽ không gặp vấn đề gì.

Trong trường hợp này, tôi đã xây dựng một "bộ đếm lượt xem" trên các bài đăng và muốn người dùng có thể sắp xếp các bài đăng được đọc nhiều nhất. Một lần nữa, các bài đăng chưa bao giờ được xem (tôi đoán điều đó khá khó xảy ra - nhưng vẫn) đã biến mất khi sắp xếp theo số lượt xem. Tôi đã thêm đoạn mã này để đảm bảo tất cả các bài đăng đều có số lượt xem:

add_action('save_post', function ($postId) {
    add_post_meta($postId, '_sleek_view_count', 0, true);
});

Vui lòng cho chúng tôi xem mã của bạn. Làm cho nó dễ dàng hơn để trả lời.
kaiser

Đầu tiên: meta_querytax_queryluôn luôn một array( array() )khi họ kết hợp nhiều mảng. Thứ hai - như đã đề cập trong câu trả lời của tôi - bạn cần sử dụng meta_value_numcho các số. Cũng có thể cần thiết để xác định thực sự meta_value_num(xem WP_Querymục nhập trang -Codex). Cuối cùng, nó không có ý nghĩa ordertrong ASC DESC hướng. Đó là không thể. Dấu phân cách không gian chỉ hoạt động orderbyvà bạn không thể yêu cầu nó sắp xếp thứ nhất ASCvà thứ hai DESC. Đó là những gì posts_clausesbộ lọc dành cho.
kaiser

Và chắc chắn rằng các meta_value_nummục của bạn là số thực . Nhìn thấy quá thường xuyên rằng ai đó nói rằng đó là một số, nhưng trên thực tế, lưu nó dưới dạng một chuỗi trong cơ sở dữ liệu.
kaiser

Cảm ơn sự giúp đỡ của bạn, tôi sẽ thử điều này và lấy lại cho bạn. Lý do ASC DESClà để nó loại trên meta_valuetrong ASCdatetrong DESC, như xa như tôi có thể nói nó hoạt động.
powerbuoy

1
@Howdy_McGee đúng vậy. Một số loại bài đăng tùy chỉnh của tôi CÓ bộ giá trị này. Một số thì không. Và các loại bài được tích hợp (như POST và PAGE) thì không. Vì vậy, bất cứ khi nào tôi cố gắng sắp xếp trên trường tùy chỉnh đó, chỉ có các bài đăng VỚI trường tùy chỉnh hiển thị.
powerbuoy

Câu trả lời:


4

Có hai giải pháp khả thi cho vấn đề này:

1. Tất cả các bài viết đều có meta

Giải pháp tốt nhất tôi tìm thấy ở đây là cung cấp cho các bài viết / sản phẩm còn lại một mức giá bằng 0. Bạn có thể làm điều này bằng tay, hoặc lặp qua tất cả các bài đăng và nếu giá trống thì hãy cập nhật nó.

Để làm cho điều này có thể quản lý được trong tương lai, bạn có thể kết nối save_postvà cung cấp cho họ một giá trị khi chúng được thêm lần đầu tiên (chỉ khi nó trống).

2. Nhiều truy vấn

Bạn có thể chạy truy vấn đầu tiên khi bạn thực hiện và lưu trữ ID của các bài đăng được trả về. Sau đó, bạn có thể chạy một truy vấn khác cho tất cả các bài đăng và ngày đặt hàng, ngoại trừ trả về ID từ truy vấn đầu tiên.

Sau đó, bạn có thể in ra hai kết quả theo thứ tự riêng biệt và bạn sẽ nhận được kết quả mong muốn.


1
Ba năm sau và tôi lại gặp vấn đề tương tự: P Phải sử dụng save_postphương pháp (Tôi đã cập nhật câu hỏi của mình với mã tôi đã sử dụng).
powerbuoy

10

Easy Peasy, vừa được thử nghiệm 2018, hiện đang sử dụng trong sản xuất.

$query->set( 'meta_query', array(
    'relation' => 'OR',
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'EXISTS'
    ),
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'NOT EXISTS'
    )
) );
$query->set( 'orderby', 'meta_value title' ); 

Điều này kiểm tra tất cả các mục có và không có khóa meta, không có giá trị được chỉ định. truy vấn meta cung cấp khóa cho thứ tự đáng tin cậy. Nó đã được thử nghiệm. Tuy nhiên, tôi không chắc nó sẽ hoạt động như thế nào khi truy vấn meta sử dụng nhiều khóa.

Ví dụ thực tế

/**
 * Modifies query before retrieving posts. Sets the 
 * `meta_query` and `orderby` param when no `orderby` 
 * param is set, (default ordering).
 * 
 * @param   WP_Query  $query  The full `WP_Query` object.
 * @return  void
 */
function example_post_ordering( $query ) {

    // if not in wp-admin, 
    // and the query is the main query, 
    // and the query is not a singular query, 
    // and the query does not have an orderby param set...
    // Note: check for post types, etc. here as desired.
    if ( ! is_admin() 
    && $query->is_main_query() 
    && ! $query->is_singular() 
    && empty( $query->get( 'orderby' ) ) ) {

        // Setting just `meta_key` is not sufficient, as this 
        // will ignore posts that do not yet, or never will have 
        // a value for the specified key. This meta query will 
        // register the `meta_key` for ordering, but will not 
        // ignore those posts without a value for this key.
        $query->set( 'meta_query', array(
            'relation' => 'OR',
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'EXISTS'
            ),
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'NOT EXISTS'
            )
        ) );

        // Order by the meta value, then by the title if multiple 
        // posts share the same value for the provided meta key.
        // Use `meta_value_num` if the meta values are numeric.
        $query->set( 'orderby', 'meta_value title' );
    }

}

add_action( 'pre_get_posts', 'example_post_ordering', 10 );

Điều này sẽ đặt hàng các bài đăng theo custom_meta_keymặc định và sẽ không bỏ qua các bài đăng mà không có giá trị cho khóa đó.


Chỉ cần đọc mã, tất cả những gì dường như làm là nhận các bài đăng có custom_meta_keyvà nhận các bài đăng mà khôngcustom_meta_key. Vui lòng bao gồm một ví dụ làm việc thực tế với sắp xếp.
powerbuoy

1
Bạn đã đúng, đó là tất cả những gì nó đang làm, nhưng dòng bên dưới chịu trách nhiệm đặt hàng theo meta_value (của khóa meta được truy vấn). $query->set( 'orderby', 'meta_value title' );(Sắp xếp theo giá trị meta, sau đó theo tiêu đề khi nhiều bài đăng có cùng giá trị cho khóa meta). Điều này nên được thực hiện trong pre_get_postshook, sử dụng $querybiến trong pass . Hãy ghi nhớ câu hỏi được hỏi là làm thế nào để đặt hàng theo giá trị meta, trong khi không bỏ qua các bài đăng không có giá trị cho khóa meta đó.
noahmason

@powerbuoy Xem ví dụ thực tế được cập nhật
noahmason

Được rồi tôi sẽ giải quyết lần sau khi tôi đối mặt với vấn đề này.
powerbuoy

1
Làm việc cho tôi trong một get_posts()cuộc gọi tùy chỉnh để chuyển các bài đăng có _featuredmeta lên đầu, sau đó đặt hàng theo ngày sau đó. Cảm ơn!
natebeaty

8

Phương pháp này sẽ trả về tất cả các bài đăng bao gồm cả những bài có và không có yêu cầu meta_key, nhưng nó sẽ làm những điều kỳ lạ khi đặt hàng.

add_action('pre_get_posts', 'my_stuff');
function my_stuff ($qry) {
    $qry->set(
        'meta_query',
        array(
            'relation' => 'OR', # Matches to this meta_query should be added to those matching the 'meta_key' query
            array(
                'key' => 'item_price', 
                'value' => 'bug #23268', 
                'compare' => 'NOT EXISTS'
            )
        )
    );

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Tôi đã tìm thấy điều này bằng cách loay hoay với tất cả các câu trả lời khác nhau cho câu hỏi này và phân tích SQL được tạo thông qua thử và lỗi. Có vẻ như cài đặt array('meta_query' => array('relation' => 'OR'))đầu ra phù hợp LEFT JOINthay vì INNER JOINđó là cần thiết để bao gồm các bài đăng thiếu siêu dữ liệu. Chỉ định NOT EXISTSngăn chặn WHEREmệnh đề lọc ra các bài đăng thiếu trường meta. Đối với điều này WP_Query, SQL được tạo là (thụt lề / dòng mới được thêm vào):

SELECT SQL_CALC_FOUND_ROWS
    wp_posts.ID
    FROM wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
    LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'item_price')
    WHERE 1=1
    AND ( wp_term_relationships.term_taxonomy_id IN (2) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
        OR wp_posts.post_status = 'private')
    AND (wp_postmeta.meta_key = 'item_price'
        -- Oh look, here we give SQL permission to choose a random
        -- row from wp_postmeta when this particular post is missing
        -- 'item_price':
        OR  mt1.post_id IS NULL )
    GROUP BY wp_posts.ID
    ORDER BY wp_postmeta.meta_value,wp_posts.post_date DESC
    LIMIT 0, 10

Kết quả là một danh sách tất cả các bài đăng có meta_value item_pricevà những bài bị thiếu item_price. Tất cả các bài viết với item_pricesẽ được đặt một cách chính xác tương đối với nhau, nhưng bài viết còn thiếu item_pricesẽ sử dụng một số ngẫu nhiên khác giá trị meta (nói, _edit_lastmà có vẻ là 1khá thường xuyên trong cơ sở dữ liệu của tôi hoặc một số siêu dữ liệu wordpress nội bộ khác đó là hoàn toàn tùy ý) cho nó wp_postmeta.meta_valuetrong các ORDER BYkhoản. Vì vậy, trong khi phương thức này gần và có thể hoạt động đối với một số dữ liệu nhất định, nó đã bị hỏng. Vì vậy, tất cả những gì tôi có thể nói là, nếu các item_pricegiá trị của bạn xảy ra không xung đột với các trường meta ngẫu nhiên mà MySQL chọn cho các bài đăng bị thiếu item_price, điều này có thể hoạt động tốt cho bạn. Nếu tất cả những gì bạn cần là một sự đảm bảo rằng bài đăng của bạn vớiitem_priceđược sắp xếp chính xác liên quan đến nhau mà không liên quan đến thứ tự của các bài viết khác, nó có thể ổn. Nhưng tôi nghĩ rằng đây chỉ là một thiếu sót trong wordpress. Xin hãy sửa lỗi cho tôi, tôi hy vọng tôi đã sai và có một cách để giải quyết vấn đề này ;-).

Có vẻ như đối với INNER JOIN wp_postmeta, MySQL đang chọn một hàng ngẫu nhiên trong số nhiều postmetahàng được liên kết với bài đăng khi meta_keythiếu từ bài đã cho. Từ góc độ SQL, chúng ta cần tìm ra cách nói wordpress với đầu ra ORDER BY mt1.meta_value. Cột này là đúng NULLkhi yêu cầu của chúng tôi meta_keybị thiếu, không giống như wp_postmeta.meta_value. Nếu chúng ta có thể làm điều đó, SQL sẽ sắp xếp các NULLmục này (các mục bị thiếu) trước bất kỳ giá trị nào khác, cung cấp cho chúng ta một thứ tự được xác định rõ: trước tiên hãy đến tất cả các bài đăng thiếu trường postmeta cụ thể, thứ hai đến các bài đăng có trường. Nhưng đó là toàn bộ vấn đề: 'orderby' => 'meta_value'chỉ có thể đề cập đến 'meta_key' => 'item_price' và không thiên vị wp_postmetaluôn luôn là một INNER JOINthay vì bao giờ LEFT JOIN, một ý nghĩa wp_postmeta.meta_valuewp_postmeta.meta_keycó thểkhông bao giờ được NULL.

Vì vậy, tôi đoán rằng tôi phải nói rằng điều này là không thể với tính năng tích hợp sẵn của wordpress WP_Queryvì nó đã được ghi lại (trong wordpress-3.9.1). Làm phiền Vì vậy, nếu bạn thực sự cần điều này để hoạt động chính xác, có lẽ bạn cần phải nối vào wordpress ở nơi khác và sửa đổi trực tiếp SQL được tạo .


Trông rất hứa hẹn! Tôi sẽ thử điều này vào lần tới khi tôi gặp vấn đề này. Tôi muốn cho bạn câu trả lời ngay bây giờ, nhưng muốn xác nhận nó hoạt động trước tiên.
powerbuoy

Điều này giữ cho tất cả mọi thứ từ hiển thị cho tôi. Không có gì cho thấy sau khi thực hiện điều này.
Jake

@Jea Yea giống nhau ở đây. Có vấn đề này một lần nữa ngày hôm nay và đã thử điều này. Trả về 0 kết quả.
powerbuoy

Các bạn đang sử dụng phiên bản wordpress nào? Tôi nghĩ rằng bài đăng này mô tả cách sử dụng API nội bộ, không có giấy tờ không được wordpress hỗ trợ và do đó có lẽ chỉ hoạt động nếu bạn sử dụng wordpress-3.9.1 hoặc không có quá nhiều phiên bản.
binki

2

Tôi nghĩ rằng tôi có một giải pháp.

Bạn có thể sử dụng hai meta_keys, một mà tất cả các bài đăng đều có (like "_thumbnail_id")meta_keybạn muốn sử dụng làm bộ lọc.

Vì vậy, đối số của bạn:

$qry->set(
    'meta_query',
    array(
        'relation' => 'OR',
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        ),
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        )
    )
);

$qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
$qry->set('order', 'ASC DESC');
$qry->set('meta_key', 'item_price');

1
Vấn đề ở đây là so sánh chuỗi trống, loại bỏ nó và nó 'value' => '', cũng hoạt động so sánh thứ hai NOT EXISTSvà không cần phải có hướng dẫn tập cuối
gật đầu

2

Vấn đề mà tất cả mọi người ở đây đang gặp phải là thứ tự của các truy vấn meta. Để sắp xếp chính xác, bạn sẽ cần đặt truy vấn "KHÔNG EXISTS" trước truy vấn "EXISTS".

Lý do cho điều này là do WordPress sử dụng meta_value của câu lệnh "LEFT THAM GIA" cuối cùng trong mệnh đề "ORDER BY".

Ví dụ:

$pageQuery = new WP_Query([
    'meta_query' => [
        'relation' => 'OR',
        ['key' => 'item_price', 'compare' => 'NOT EXISTS'], // this comes first!
        ['key' => 'item_price', 'compare' => 'EXISTS'],
    ],
    'order' => 'DESC',
    'orderby' => 'meta_value_num',
    'post_status' => 'publish',
    'post_type' => 'page',
    'posts_per_page' => 10,
]);

1

Nếu phù hợp, bạn có thể thêm một giá trị meta mặc định mỗi khi bài đăng được lưu hoặc cập nhật, nếu giá trị meta không tồn tại.

function addDefaultMetaValue($post_id) {
    add_post_meta($post_id, 'item_price', 0, true);
}
add_action('save_post', 'addDefaultMetaValue');

Nếu bạn đang sử dụng một loại bài tùy chỉnh, thay thế add_action('save_post', 'addDefaultMetaValue');bằng add_action('save_post_{post_type}', 'addDefaultMetaValue');ví dụadd_action('save_post_product', 'addDefaultMetaValue');


1

Tôi đã có vấn đề một mình đối với các giá trị meta số và chỉ ra rằng thứ tự của truy vấn cũng rất quan trọng. Đối với tôi, NOT EXISTStruy vấn phải là cái đầu tiên.

Thí dụ:

$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_query', [
    'relation' => 'OR',
    [ 'key' => 'your_meta_name', 'compare' => 'NOT EXISTS' ],
    [
        'key' => 'your_meta_name',
        'compare' => 'EXISTS',
    ],
] );

Ngoài ra, điều quan trọng để có được hướng đúng cho các giá trị số là tổng quát ’orderby’được đặt thành ’meta_value_num’. Nếu không, bạn có kết quả lạ cho các giá trị số, ví dụ:

1, 2, 20, 21, 3, 4, 5

Thay vì:

1, 2, 3, 4, 5 HỒ 20, 21


1

Tôi cũng gặp phải một vấn đề tương tự và giải pháp sau đây đã giúp tôi:

$args = array(
'post_type' => 'kosh_products',
'posts_per_page' => -1,
'meta_query' => array(
    'relation' => 'OR',
    'category_sort_order' => array(
        'key' => '_sort_order',
        'compare' => 'EXISTS'
    ),
    'category_sort_order_not_exists' => array(
        'key' => '_sort_order',
        'compare' => 'NOT EXISTS'
    ), 
),
'orderby' => array( 
    'category_sort_order' => 'ASC',
    'date' => 'ASC'
));
$query = new WP_Query( $args );

Tôi đã tìm thấy một mô tả về WordPress Codex với tiêu đề " 'orderby' với nhiều 'meta_key's ": https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameter nhập mô tả hình ảnh ở đây


0

Có một orderbygiá trị có thể meta_valuecho điều đó.

$query = new WP_Query( array ( 
    'meta_key'   => 'your_keys_name',
    'orderby'    => 'meta_value',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'your_meta_key',
         'value'   => '',
         'compare' => 'NOT EXISTS',
         // 'type'    => 'CHAR',
    ) )
) );

Nếu bạn có các giá trị số, chỉ cần sử dụng meta_value_numthay thế.

Tuyên bố từ chối trách nhiệm: Điều này không được thử nghiệm, nhưng nó sẽ hoạt động. Điểm là bạn cần xác định meta_keykeygiá trị của bạn . Khác, bạn không thể so sánh với các giá trị không tồn tại, điều này sẽ giúp truy vấn cả hai loại bài đăng. Đó là một loại hack-ish, nhưng miễn là nó hoạt động ...


Cảm ơn câu trả lời của bạn, xin vui lòng kiểm tra câu hỏi cập nhật của tôi, tôi không chắc tôi đã hiểu đúng về bạn.
powerbuoy

Tôi vẫn chưa thực hiện được công việc này vì vậy nếu bạn có giải pháp tôi muốn biết tôi đang làm gì sai. Ngoài ra, tôi đặt tiền thưởng cho SO nếu bạn muốn yêu cầu nó: stackoverflow.com/questions/17016770/
Kẻ

1
Hai điều. 'your_keys_name''your_meta_key'cả hai nên là cùng một chuỗi thay vì khác biệt, nếu không, có vẻ như bạn đã hiểu nhầm câu hỏi. Thứ hai, tôi đã kiểm tra điều này trên thiết lập cục bộ của mình và nó không bao gồm bất kỳ bài đăng nào có khóa tồn tại (thông qua meta_query) và loại trừ bất kỳ bài đăng nào mà khóa bị thiếu (thông qua meta_key) dẫn đến không có bài đăng nào hiển thị. Tuy nhiên, câu trả lời này là một bước tiến tới một cái gì đó ít nhất là từ ;-).
binki

1
Ồ, thật thú vị, câu trả lời này không hoạt động nếu bạn chỉ cần thêm 'relation' => 'OR'vào meta_query. Thứ lập dị o_o.
binki

@binki Chỉ cần gửi một chỉnh sửa cho câu hỏi của tôi và thay đổi các bit bạn nghĩ nên được thay đổi. Đây là một trang web hướng đến cộng đồng :)
kaiser

0

Tôi nghĩ rằng những gì @kaiser đã cố gắng làm là yêu cầu truy vấn trả về tất cả các bài đăng có khóa meta đó bằng cách áp dụng một loại hình giả trong điều kiện để không lọc bất kỳ bài đăng nào trong số đó. Vì vậy, nếu bạn biết tất cả các giá trị mà các trường tùy chỉnh của bạn có thể nhận là x, y, z, bạn có thể nói "WHERE meta_key IN (x, y, z) " nhưng ý tưởng là bạn có thể tránh vấn đề đó cùng nhau bằng cách nói ! = (' ') :

$query = new WP_Query( array ( 
    'orderby'    => 'meta_value_num',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'item_price',
         'value'   => '',
         'compare' => '!=',
    ) )
) );

Cũng không được thử nghiệm nhưng cảm giác như nó đáng để thử :-).


1
Không thể thực sự kiểm tra điều này ngay bây giờ, nhưng khá chắc chắn rằng sẽ chỉ trả lại các bài đăng nơi item_price được đặt và không phải là ''.
powerbuoy

0

Cuối cùng tôi đã khắc phục điều này bằng một chút hack (IMHO), nhưng nó đã làm việc cho tôi trong trường hợp của tôi.

Bạn có thể nối vào các bộ lọc post_join_pagedpost_orderby để cập nhật chuỗi tham gia và thứ tự. Điều này sẽ cho phép bạn đặt hàng theo bất cứ điều gì bạn muốn miễn là bạn tham gia trước chứ không phải WP_Query giả định rằng trường phải tồn tại cho bài đăng cụ thể đó. Sau đó bạn có thể loại bỏ meta_key, orderby, và `theo thứ tự từ args WP_Query của bạn.

Dưới đây là một ví dụ. Ở đầu mỗi hàm tôi phải thoát ra trong một số trường hợp nhất định vì nó sẽ thêm phần này vào mọi thứ sử dụng WP_Query. Bạn có thể cần phải sửa đổi điều đó để phù hợp với nhu cầu cụ thể của bạn.

Tài liệu về hai bộ lọc này thật đáng buồn vì thiếu ... chúc may mắn! :)

add_filter('posts_join_paged', 'edit_join', 999, 2);
add_filter('posts_orderby', 'edit_orderby', 999, 2);

/**
 * Edit join
 *
 * @param string $join_paged_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_join($join_paged_statement, $wp_query)
{
    global $wpdb;
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $join_paged_statement;
    }

    $join_to_add = "
        LEFT JOIN {$wpdb->prefix}postmeta AS my_custom_meta_key
            ON ({$wpdb->prefix}posts.ID = my_custom_meta_key.post_id
                AND my_custom_meta_key.meta_key = 'my_custom_meta_key')
    ";

    // Only add if it's not already in there
    if (strpos($join_paged_statement, $join_to_add) === false) {
        $join_paged_statement = $join_paged_statement . $join_to_add;
    }

    return $join_paged_statement;
}

/** 
 * Edit orderby
 *
 * @param string $orderby_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_orderby($orderby_statement, $wp_query)
{
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $orderby_statement;
    }

    $orderby_statement = "my_custom_meta_key.meta_value DESC";

    return $orderby_statement;
}

Các mã hoạt động. Nhưng meta_value được xử lý như một chuỗi. Vì vậy, 6 được đánh giá cao hơn 50. Bất kỳ sửa đổi nào có thể coi chúng là số?
Lái xe

@Driveralle cast(my_custom_meta_key.meta_value as unsigned) DESCnên thực hiện thủ thuật ...
tfrommen 2/2/2017

1
Cảm ơn @tfrommen. $orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";làm việc tuyệt vời
Lái xe

0

Giải pháp này hiệu quả với tôi:

add_action( 'pre_get_posts', 'orden_portfolio' );
function orden_portfolio( $query ) {

    if( ! is_admin() ) {

        $query->set( 'orderby', 'meta_value_num' );
        $query->set( 'order', 'ASC' );
        $query->set( 'meta_query', [
            'relation' => 'OR',
            [ 
                'key' => 'ce_orden', 
                'compare' => 'NOT EXISTS' ],
            [
                'key' => 'ce_orden',
                'compare' => 'EXISTS',
            ],
        ] );

        return $query;

    }

}

Tuy nhiên, giải pháp này trước tiên hiển thị các bản ghi với null meta_value. Giải pháp khác này hiển thị thứ tự ASC và null ở cuối:

function custom_join($join) {
    global $wpdb;

    if( ! is_admin() ) {
        $join .= $wpdb->prepare(
        ' LEFT JOIN ' . $wpdb->postmeta . ' cpm ON cpm.post_id = ' . $wpdb->posts . '.ID AND cpm.meta_key = %s'
        , 'ce_orden' );
    }

    return $join;
}

add_filter('posts_join','custom_join');

function custom_orderby($orderby_statement){
    global $wpdb;

    if ( ! is_admin() ) {
        $orderby_statement = "CAST( COALESCE(cpm.meta_value,99999) as SIGNED INTEGER) ASC";
    }

    return $orderby_statement;
}

add_filter('posts_orderby','custom_orderby', 10, 2 ); 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.