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' => '<'
        )
    )
);
v3nt
źródło
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.

Jan Fabry
źródło
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';
}
Alex Older
źródło
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.

Otto
źródło