Combinando consultas con diferentes argumentos por tipo de publicación

11

Estoy construyendo una sección en un sitio donde fusiono dos tipos de publicaciones diferentes en un bucle y luego las visualizo al azar. El problema es que me cuesta encontrar una manera de limitar la cantidad de publicaciones por tipo.

Esto es lo que he intentado:

  • Se puede lograr una consulta con múltiples tipos de publicaciones con una matriz:

    $args = array( 'post_type' => array( 'photos', 'quotes' ), ...

    ... pero no puede limitarse a un cierto número de publicaciones por tipo.

  • Fusionar dos matrices de argumentos de consulta antes de ejecutar WP_Query en él:

    $photos = array( 'post_type' => 'photos', 'posts_per_page' => 15, 'orderby' => 'rand' );
    $quotes = array( 'post_type' => 'quotes', 'posts_per_page' => 5, 'orderby' => 'rand' );
    
    $args = $photos + $quotes;
    // Also tried array_merge( $photos, $quotes );
    

    No hay suerte en esto. Lo que sucede es que la última variable $quotessobrescribe $photosy solo muestra las comillas.

  • Fusionar dos objetos WP_Query juntos mediante la conversión de texto:

    $photos_query = new WP_Query( $photos );
    $quotes_query = new WP_Query( $quotes );
    $result = (object)array_merge( (array)$photos_query, (array)$quotes_query );
    

... y así.

Probablemente podría usar una consulta SQL directamente a la base de datos, pero necesito poder combinar estos dos tipos de publicaciones separadas para un bucle, organizadas al azar, y limitadas a una cierta cantidad de publicaciones por tipo.

¡Gracias por tu ayuda!

Andy Merskin
fuente

Respuestas:

16

Una forma es personalizar la consulta SQL ejecutada usando posts_clausesu otros filtros similares. Para encontrarlos, busque posts_clausesen "wp-includes / query.php" y vea la serie de filtros justo antes de esta línea. Estos juntos son capaces de personalizar cualquier parte de la consulta.

Otra cosa que puede hacer es fusionar manualmente las publicaciones consultadas en los objetos

$photos_query = new WP_Query( $photos );
$quotes_query = new WP_Query( $quotes );
$result = new WP_Query();

// start putting the contents in the new object
$result->posts = array_merge( $photos_query->posts, $quotes_query->posts );

// here you might wanna apply some sort of sorting on $result->posts

// we also need to set post count correctly so as to enable the looping
$result->post_count = count( $result->posts );
Mridul Aggarwal
fuente
Su segunda solución (sin el SQL) hizo el truco! Ahora tengo control completo sobre lo que está pasando en esa consulta final antes de entrar en el ciclo. ¡Gracias por tu ayuda!
Andy Merskin
1
El primero es difícil pero más eficiente (en el segundo todavía hay 2 consultas de bases de datos). Yo diría que todo se reduce a preferencias personales
Mridul Aggarwal
¡Estaría extremadamente interesado en una forma de lograr la primera solución! Los filtros necesarios, etc. ¿Esto requiere UNIONalgún tipo de sql para cada post_type?
Solomon Closson
@SolomonClosson este filtro puede ayudar- codex.wordpress.org/Plugin_API/Filter_Reference/posts_clauses
Mridul Aggarwal
7

@mridual aggarwal su respuesta es muy buena pero desafortunadamente no combina realmente los 2 wp_query, solo muestra las publicaciones de ambos en orden, quiero decir 5 publicaciones de la primera y 5 de la segunda, pero no ordenadas todas en una, así que tengo esto solución y logró exactamente el objetivo para mí al menos

<?php
$term = get_term_by( 'slug', get_query_var( 'tag' ), "post_tag" );
$tagslug = $term->slug;
$post_types = get_post_types('','names');
?>
<?php
//first query
$blogposts = get_posts(array(
    'tag' => $tagslug, //first taxonomy
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
//second query
$authorposts = get_posts(array(
    'bookauthor' => $tagslug, //second taxonomy
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
$mergedposts = array_merge( $blogposts, $authorposts ); //combine queries

$postids = array();
foreach( $mergedposts as $item ) {
$postids[]=$item->ID; //create a new query only of the post ids
}
$uniqueposts = array_unique($postids); //remove duplicate post ids

$posts = get_posts(array(
        //new query of only the unique post ids on the merged queries from above
    'post__in' => $uniqueposts,  
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
foreach( $posts as $post ) :
setup_postdata($post);
?>
// posts layout
<?php endforeach; ?>
<?php wp_reset_postdata();?>
adnan
fuente