Zamówić według meta wartości lub daty?


10

Mam niestandardowe pole o nazwie, startDateale jest tylko na kilku zdarzeniach. Zastanawiałem się, czy nie jest ustawiony dla posta, którego mógłbym użyć post_datedo wygenerowania listy postów?

// if meta_key _postmeta.startDate isn't set get the rest by posts.post_date

query_posts(
    array(
        array(
            'posts_per_page' => 10,
            'meta_key' => 'startDate',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<',
            'orderby' => 'meta_value',
            'order' => 'ASC'
        ), 
        array(
            'meta_key' => 'post_date',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<'
        )
    )
);

czy post_date jest polem niestandardowym?
— Bainternet

IW zakładając, że jest to domyślne pole publikowane wordpress, choć może być źle? Tak czy inaczej, chciałbym użyć domyślnej daty ...
— v3nt

ok, więc nie jest to pole meta jest w tabeli postów
— Bainternet

Naprawiono argumenty zapytania, mam nadzieję, że wcale nie zmieniło tego, co ilustrujesz, w razie potrzeby możesz cofnąć.
— t31os

pozdrawiam t31os - edytowałem go ponownie, aby był bardziej przejrzysty. Musisz wybrać zawartość starszą niż TERAZ, używając startDate, a jeśli nie ustawiono startDate, użyj domyślnej daty post_date.
— v3nt

Odpowiedzi:


11

Jeśli potrafisz wyjaśnić to w SQL, możesz zapytać o to! Istnieją trzy miejsca, w których chcemy zmienić domyślne zapytanie:

SELECT wp_posts.*
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND wp_postmeta.meta_key = 'startDate'
    AND CAST(wp_postmeta.meta_value AS CHAR) < '2011-03-23'
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 0, 10
  • Złączenie powinno być złączeniem z lewej strony
  • Klauzula gdzie
  • Kolejność

Sprzężenie i klauzula where są dodawane za pomocą _get_meta_sql()funkcji . Dane wyjściowe są filtrowane, dzięki czemu możemy się do niego podłączyć:

add_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' );
function wpse12814_get_meta_sql( $meta_sql )
{
    // Move the `meta_key` comparison in the join so it can handle posts without this meta_key
    $meta_sql['join'] = " LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate') ";
    $meta_sql['where'] = " AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '" . date('Y-m-d') . "')";
    return $meta_sql;
}

Klauzula zamówienia jest filtrowana przez posts_orderby:

add_filter( 'posts_orderby', 'wpse12814_posts_orderby' );
function wpse12814_posts_orderby( $orderby )
{
    $orderby = 'COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC';
    return $orderby;
}

To daje nam następujące zapytanie SQL:

SELECT wp_posts.*
FROM wp_posts
LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate')
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '2011-03-23')
GROUP BY wp_posts.ID
ORDER BY COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC
LIMIT 0, 10

Pamiętaj, aby odhaczyć filtry po wykonaniu zapytania, w przeciwnym razie zepsujesz również inne zapytania. I jeśli to możliwe , nie powinieneś dzwonić do query_posts()siebie , ale modyfikować główne zapytanie wysyłane przez WordPress podczas konfigurowania strony.


2
Bardzo eleganckie rozwiązanie, nie pomyślałbym o takim użyciu COALESCE. Radziłbym po prostu nie zakładać domyślnego prefiksu „wp_” i zamiast tego użyć {$ wpdb-> prefiks} ...
— goldenapples

@goldenapples: Tak, możesz je uogólnić, ale jest on już tak specyficzny dla tego zapytania (zepsuje inne zapytania z częścią meta), że myślałem, że nie jest to konieczne.
— Jan Fabry

Dzięki Jan - to jest otwieracz do oczu! Nadal masz do czynienia z wordpress i zastanawiasz się, jak to się nazywa na mojej stronie? A jak miałbym to „odpiąć”? tj. // $ theQuery ... następnie <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
— v3nt

@ Daniel: Możesz umieścić funkcje w functions.phppliku motywu . Następnie tuż przed wykonaniem zapytania umieść dwa add_filter()wiersze. Po zapytaniu piszesz, remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );aby je ponownie usunąć.
— Jan Fabry

ah - to wszystko ma teraz sens i działa też! Wielkie dzięki, Jan. To się przyda ...
— v3nt

0

spróbuj czegoś w stylu:

$postedtime = get_post_meta($post->ID, 'startDate');

if($postedtime != null){
$orderby = $postedtime;

}else{
$orderby = 'date';
}

dziękuję alex, ale nie wiesz, jak to się angażuje w pętli?
— v3nt

doh! kiedy zapytanie_posts (tablica ('orderby' => $ orderby))
— Alex Older

0

Wywołanie wywołania zapytania stanowi tylko jedno zapytanie, a nie dwa. Więc nie, nie możesz mieć dwóch osobnych zapytań, a następnie konkatenować wyników.

Pamiętaj, że wybierasz tutaj zestaw wpisów, a następnie je wyświetlasz. Ten zestaw jest wybierany jednocześnie. Jeśli chcesz uzyskać dwa oddzielne zestawy postów, a następnie połączyć je, to musisz zrobić to sam z get_posts lub podobnym.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.