web-dev-qa-db-fra.com

Ordre par méta valeur ou date?

Vous avez un champ personnalisé appelé startDate mais ce n'est que sur quelques événements. Je me demandais si elle n'était pas définie pour une publication, puis-je utiliser post_date pour générer la liste des publications?

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

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 où
  • L'ordre

La jointure et la clause where sont ajoutées via la fonction _get_meta_sql() . 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 à travers 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 effectué votre requête, sinon vous risquez de gâcher d'autres requêtes. Et si possible vous ne devez pas appeler query_posts() vous-même , mais modifier la requête principale effectuée par WordPress lors de la configuration de la page.

11
Jan Fabry

essayez quelque chose comme:

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

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

}else{
$orderby = 'date';
}
0
Alex Older

Une requête publie un appel ne fait qu'une 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 les affichez. Cet ensemble est sélectionné en une fois. Si vous souhaitez obtenir deux ensembles distincts de publications, puis les fusionner, c’est quelque chose que vous devrez faire vous-même avec get_posts ou similaire.

0
Otto