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

¿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.


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

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.