Trier par méta-valeur ou par date?

10

Vous avez un champ personnalisé appelé startDate mais il ne concerne que quelques événements. Je me demandais s’il n’était pas défini pour un message, je pourrais utiliser post_date pour générer la liste des messages?

// 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' => '<'
        )
    )
);
    
posée v3nt 23.03.2011 - 13:40

3 réponses

11

Si vous pouvez l'expliquer en SQL, vous pouvez l'interroger! Nous souhaitons modifier la requête par défaut à trois endroits:

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
  • La jointure doit être une jointure gauche
  • La clause where
  • La commande

La jointure et la clause where sont ajoutées via la _get_meta_sql() fonction . La sortie est filtrée, nous pouvons donc y accrocher:

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 clause order est filtrée via 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;
}

Cela nous donne la requête SQL suivante:

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

N'oubliez pas de décrocher les filtres après avoir posé votre requête, sinon vous risquez également de gâcher d'autres requêtes. Et si possible vous ne devriez pas appelez query_posts() vous-même , mais modifiez la requête principale effectuée par WordPress lors de la configuration de la page.

    
réponse donnée Jan Fabry 23.03.2011 - 22:06
0

essayez quelque chose comme:

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

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

}else{
$orderby = 'date';
}
    
réponse donnée Alex Older 23.03.2011 - 16:00
0

Un appel à une requête publie une seule requête, pas deux. Donc, non, vous ne pouvez pas le faire faire deux requêtes distinctes et ensuite concaténer les résultats.

N'oubliez pas que vous sélectionnez un ensemble de messages ici, puis vous les affichez. Cet ensemble est sélectionné en une fois. Si vous souhaitez obtenir deux ensembles distincts d’articles et les fusionner, c’est quelque chose que vous devrez faire vous-même avec get_posts ou similaire.

    
réponse donnée Otto 23.03.2011 - 20:15

Lire d'autres questions sur les étiquettes