Ordina per meta valore o data?


10

Ho chiamato un campo personalizzato startDatema è solo su alcuni eventi. Mi chiedevo se non è impostato per un post che potrei usare post_dateper generare l'elenco dei post?

// 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' => '<'
        )
    )
);

post_date è un campo personalizzato?
Bainternet,

presumo che sia il campo pubblicato wordpress predefinito sebbene possa essere sbagliato? Ad ogni modo, mi piace usare la data predefinita ...
v3nt

ok, quindi non è un meta campo è nella tabella dei post
Bainternet,

Risolti i tuoi argomenti di ricerca, spero che non abbia distorto affatto quello che stavi illustrando, sentiti libero di tornare indietro se necessario.
t31os,

saluti t31os - modificato di nuovo per renderlo più chiaro. È necessario per selezionare i contenuti più vecchi di NOW utilizzando startDate e se startDate non è stato impostato, utilizzare la data post post_date predefinita.
v3nt

Risposte:


11

Se puoi spiegarlo in SQL, puoi richiederlo! Esistono tre posizioni in cui vogliamo modificare la query predefinita:

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
  • Il join dovrebbe essere un join sinistro
  • La clausola Where
  • L'ordine

Il join e la clausola where vengono aggiunti tramite la _get_meta_sql()funzione . L'output è filtrato, quindi possiamo agganciarci:

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;
}

La clausola d'ordine viene filtrata attraverso 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;
}

Questo ci dà la seguente query 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

Ricorda di sganciare i filtri dopo aver eseguito la query, altrimenti confonderai anche altre query. E, se possibile, non si dovrebbe chiamare query_posts()te stesso , ma modificare la principale interrogazione post che è fatto da WordPress durante l'impostazione della pagina.


2
Soluzione molto elegante, non avrei mai pensato di usare COALESCE in quel modo. Vorrei solo consigliare di non assumere il prefisso "wp_" predefinito e di utilizzare invece {$ wpdb-> prefisso} ...
goldenapples

@goldenapples: Sì, potresti generalizzarlo, ma è già così specifico per questa query (rovinerà altre query con una meta-parte), che pensavo non fosse necessario.
Jan Fabry,

Grazie Jan - questo è un vero toccasana! Stai ancora facendo i conti con wordpress e ti chiedi dove questo viene chiamato sulla mia pagina? E come lo "sgancerei"? cioè // $ theQuery ... then <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
v3nt,

@daniel: puoi inserire le funzioni nel functions.phpfile del tuo tema . Quindi, immediatamente prima di eseguire la query, posizionare le due add_filter()righe. Dopo la query scrivi remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );per rimuoverli di nuovo.
Jan Fabry,

ah - ora è tutto sensato e funziona anche!
Mille

0

prova qualcosa sulla falsariga di:

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

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

}else{
$orderby = 'date';
}

grazie alex ma non sei sicuro di come sia coinvolto il loop?
v3nt

doh! quando query_posts (array ('orderby' => $ orderby))
Alex Older

0

Una chiamata ai post di query crea solo una query, non due. Quindi no, non puoi fargli fare due query separate e poi concatenare i risultati.

Ricorda, stai selezionando alcuni set di post qui, quindi li visualizzi. Quel set è selezionato tutto in una volta. Se vuoi ottenere due set separati di post e poi unirli, è qualcosa che dovrai fare da solo con get_posts o simili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.