programing

WordPress - 메타 값이 존재하는 경우 메타 값에 따라 순서를 지정하고, 존재하지 않는 경우 날짜를 지정합니다.

oldcodes 2023. 11. 5. 14:58
반응형

WordPress - 메타 값이 존재하는 경우 메타 값에 따라 순서를 지정하고, 존재하지 않는 경우 날짜를 지정합니다.

사용자가 사용자 정의 필드별로 검색 결과를 정렬할 수 있도록 합니다.

사용하고 있습니다.pre_get_posts필터는 하나만 빼고 다 잘 작동합니다.

문제는 사용자 지정 필드를 사용하여 정렬할 때 해당 사용자 지정 필드가 설정된 게시물만 검색에 표시된다는 것입니다.

사용자가 검색 결과를 정렬하는 방법을 변경할 때 검색 결과의 수가 변경되므로 이를 허용할 수 없습니다.

대신 제가 원하는 것은 사용자 지정 필드가 있는 게시물이 순서대로 먼저 나타나고 나머지 게시물은 날짜에 맞춰 정렬되어 나타나는 것입니다.

제가 가지고 있는 관련 코드는 다음과 같습니다.

<?php
add_filter('pre_get_posts', 'h5b_search_pre_get_posts');

function h5b_search_pre_get_posts ($qry) {
    $validOrders    = array('price', 'date', 'popularity');
    $orderBy        = (isset($_GET['myorder']) and in_array($_GET['myorder'], $validOrders)) ? $_GET['myorder'] : 'price';

    if ($qry->is_main_query() and $qry->query_vars['s'] != '') {
        # This only includes the posts that have "item_price" set
        if ($orderBy == 'price') {
            $qry->set('orderby', 'meta_value_num date');
            $qry->set('order', 'ASC DESC');
            $qry->set('meta_key', 'item_price');
        }
        # This works fine and includes all posts (obviously)
        elseif ($orderBy == 'date') {
            $qry->set('orderby', 'date');
            $qry->set('order', 'DESC');
        }
    }
}

편집: 실제 MySQL 쿼리 모습은 다음과 같습니다.어떻게 하면 이것을 변경할 수 있을까요?wp_postmeta.meta_value존재하는 경우 - 존재하지 않는 경우 날짜 정렬?

SELECT 
    SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM 
    wp_posts 
INNER JOIN 
    wp_postmeta 
ON 
    (wp_posts.ID = wp_postmeta.post_id) 
WHERE 
    1=1 AND 
    ((
        (wp_posts.post_title LIKE '%lorem%') OR 
        (wp_posts.post_content LIKE '%lorem%')
    )) AND 
    wp_posts.post_type IN ('post', 'page', 'attachment', 'items', 'locations') AND 
    (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') AND 
    (wp_postmeta.meta_key = 'item_price' ) 
GROUP BY 
    wp_posts.ID 
ORDER BY 
    wp_postmeta.meta_value+0,wp_posts.post_date DESC LIMIT 0, 6

가급적이면 저는 그것을 사용해서 해결하고 싶습니다.WP_Querymethods 하지만 필요하다면 나만의 SQL을 실행하는 것을 고려해 볼 수 있습니다.

편집2: 다음과 같은 것을 사용해야 한다는 느낌이 듭니다.IF NOT NULL- 당신은 그것을 어떻게 하겠습니까?WP_Query? 그게 가능하긴 해요?

편집(다시):같은 질문이 있습니다. (제 생각에는 :P): https://wordpress.stackexchange.com/questions/28409/way-to-include-posts-both-with-without-certain-meta-key-in-args-for-wp-query

예쁘게(또는 최적화)되지는 않겠지만, 제 생각에는 당신이 사용할 수 있을 것 같습니다.IF아니면CASE여기:

ORDER BY 
CASE wp_postmeta.meta_value WHEN IS NOT NULL THEN wp_postmeta.meta_value END ASC,
CASE wp_postmeta.meta_value WHEN IS NULL THEN wp_posts.post_date END DESC

참고: 제가 직접 시도해보지 않았기 때문에 구문 오류가 있을 수 있지만 이론적으로는 효과가 있을 것입니다.

더 읽기: If 문을 ORDER BY에 추가할 수 있습니까?

여기서 문제는 데이터가 날짜 열로 정렬되지 않는 것이 아니라 비어 있는 데이터가 없다는 것입니다.meta_value반환된

메타가 지정되지 않은 항목이 표시되지 않는 이유는 다음과 같이 필터링될 수 있기 때문입니다.INNER JOIN그런 경우에 대해서는,wp_postmeta.post_id is null. 조인을 다음으로 변경합니다.LEFT OUTER JOIN.

SELECT 
    SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM 
    wp_posts 


LEFT OUTER JOIN

    wp_postmeta 
ON 
    (wp_posts.ID = wp_postmeta.post_id) 
WHERE 
    1=1 AND 
    ((
        (wp_posts.post_title LIKE '%lorem%') OR 
        (wp_posts.post_content LIKE '%lorem%')
    )) AND 
    wp_posts.post_type IN ('post', 'page', 'attachment', 'items', 'locations') AND 
    (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') AND 
    (wp_postmeta.meta_key = 'item_price'  OR wp_postmeta.meta_key is NULL ) 
GROUP BY 
    wp_posts.ID 
ORDER BY 
    wp_postmeta.meta_value+0,wp_posts.post_date DESC LIMIT 0, 6

갱신하다

조인 유형을 변경하려면 다음과 같이 하십시오.WP_Query사용하다$join설정할 재산posts_joinPlugin API/Filter Reference/posts join에 설명된 대로 filter

WP_Query Class 참조도 참조하십시오.

알아요, 이 스레드는 이미 6개월 정도 되었는데도 충분한 답이 없었던 것 같아요.저는 그 문제의 원작자와 정확히 같은 문제에 부딪치고 있었습니다.이것이 제가 작업하고 원하는 결과를 반환하기 위해 찾은 마지막 SQL 쿼리입니다.

SELECT SQL_CALC_FOUND_ROWS * 
FROM wp_posts 
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 
LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'showPostInBanner' AND mt1.meta_value='1') 
LEFT JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) 
WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (34,47,51,50,68,78,82,90,97,155,227,253,285,294,314,373,425,436,452,456,521,627,667,680,694,710,730,741,751) ) 
AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID 
ORDER BY mt1.meta_value+0 DESC, wp_posts.post_date DESC LIMIT 0, 4

이를 바탕으로 쿼리가 작동하려면 다음과 같이 보여야 합니다(새로운 오류를 포함하지 않은 경우 - 하지만 지금 쿼리가 작동합니다).

SELECT SQL_CALC_FOUND_ROWS * 
FROM wp_posts 
LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'showPostInBanner' AND mt1.meta_value='1') 
LEFT JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) 
WHERE 1=1 AND ((
        (wp_posts.post_title LIKE '%lorem%') OR 
        (wp_posts.post_content LIKE '%lorem%')
    )) AND 
AND wp_posts.post_type IN ('post', 'page', 'attachment', 'items', 'locations') AND 
    (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private')
GROUP BY wp_posts.ID 
ORDER BY mt1.meta_value+0 DESC, wp_posts.post_date DESC LIMIT 0, 6

편집2의 경우:네, meta_query를 사용하여 가능합니다. 시도해보세요.

'meta_query' => array(
    array(
                        'key' => 'meta_key',
                        'value' => 'some value', //try to put null here 
                        'compare' => '!='
                        )
    ),

해결책이 있다고 생각합니다.

두 개의 meta_key를 사용합니다. 하나는 모든 게시물이 가지고 있는 (예: "_thumbnail_id") meta_key를 사용합니다.그래서 당신의 args:

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

$qry->set('orderby', 'meta_value date'); 
$qry->set('order', 'ASC DESC'); 
$qry->set('meta_key', 'item_price');

언급URL : https://stackoverflow.com/questions/17016770/wordpress-order-by-meta-value-if-it-exists-else-date

반응형