¿Ordenar por metavalor o fecha?

10

Tengo un campo personalizado llamado startDatepero solo en algunos eventos. Me preguntaba si no está configurado para una publicación que podría usar post_datepara generar la lista de publicaciones.

// 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
fuente
¿post_date es un campo personalizado?
Bainternet
Supongo que es el campo publicado de WordPress predeterminado, aunque puede estar equivocado. De cualquier manera, la identificación desea usar la fecha predeterminada ...
v3nt
ok, no es un
metacampo
Se corrigieron los argumentos de tu consulta, espero que no haya sesgado lo que estabas ilustrando, no dudes en volver si es necesario.
t31os
saludos t31os - lo editó nuevamente para hacerlo más claro. Lo necesita para seleccionar contenido anterior a NOW usando startDate, y si startDate no se ha configurado, use la fecha predeterminada post_date.
v3nt

Respuestas:

11

Si puede explicarlo en SQL, ¡puede consultarlo! Hay tres lugares donde queremos cambiar la consulta predeterminada:

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 unión debe ser una unión izquierda
  • La cláusula where
  • El orden

La unión y la cláusula where se agregan a través de la _get_meta_sql()función . La salida se filtra, por lo que podemos conectarla:

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 cláusula de orden se filtra a través de 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;
}

Esto nos da la siguiente consulta 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

Recuerde desenganchar los filtros después de que realizó su consulta, de lo contrario también estropeará otras consultas. Y si es posible, no debe llamarse a query_posts()sí mismo , sino modificar la consulta de publicación principal que realiza WordPress mientras configura la página.

Jan Fabry
fuente
2
Solución muy elegante, no habría pensado en usar COALESCE así. Solo recomendaría no asumir el prefijo predeterminado 'wp_' y usar {$ wpdb-> prefix} en su lugar ...
goldenapples
@goldenapples: Sí, podría generalizarlo, pero ya es tan específico para esta consulta (desordenará otras consultas con una metaparte), que pensé que esto no era necesario.
Jan Fabry
Gracias Jan, ¡eso es una revelación! ¿Todavía te estás familiarizando con WordPress y te preguntas dónde se llama esto en mi página? ¿Y cómo lo 'desengancharía'? es decir, // $ theQuery ... luego <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
v3nt
@daniel: Puedes colocar las funciones en el functions.phparchivo de tu tema . Luego, justo antes de ejecutar la consulta, coloca las dos add_filter()líneas. Después de la consulta, escribe remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );para eliminarlos nuevamente.
Jan Fabry
¡Ah, todo eso tiene sentido ahora y también funciona! Muchas gracias Jan. Eso será útil ...
v3nt
0

intente algo como:

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

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

}else{
$orderby = 'date';
}
Alex Older
fuente
thankx alex pero no estoy seguro de cómo esto se involucra en el ciclo?
v3nt
doh! when query_posts (array ('orderby' => $ orderby))
Alex Older
0

Una consulta que realiza una llamada realiza solo una consulta, no dos. Entonces no, no puede hacer que haga dos consultas separadas y luego concatene los resultados.

Recuerde, está seleccionando un conjunto de publicaciones aquí y luego mostrándolas. Ese conjunto se selecciona de una vez. Si desea obtener dos conjuntos separados de publicaciones y luego fusionarlas, entonces eso es algo que tendrá que hacer usted mismo con get_posts o similar.

Otón
fuente