Combinando consultas con diferentes argumentos por tipo de entrada

5 nov 2012, 09:31:58
Vistas: 32.1K
Votos: 16

Estoy construyendo una sección en un sitio donde estoy combinando dos tipos diferentes de entradas en un solo bucle, y luego mostrándolos aleatoriamente. El problema es que me está costando encontrar una manera de limitar la cantidad de entradas por tipo.

Esto es lo que he intentado:

  • Una consulta con múltiples tipos de entrada se puede lograr con un array:

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

    ... pero no se puede limitar a un número determinado de entradas por tipo.

  • Combinar dos arrays de argumentos de consulta antes de ejecutar WP_Query:

    $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;
    // También probé array_merge( $photos, $quotes );
    

    Sin éxito en esto. Lo que sucede es que la última variable $quotes sobrescribe $photos y solo muestra las citas.

  • Combinar dos objetos WP_Query juntos mediante conversión de tipos:

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

... y así sucesivamente.

Probablemente podría usar una consulta SQL directamente a la base de datos, pero necesito poder combinar estos dos tipos de entradas separados en un solo bucle, ordenados aleatoriamente, Y limitados a una cierta cantidad de entradas por tipo.

¡Gracias por tu ayuda!

0
Todas las respuestas a la pregunta 2
5
21

Una forma es personalizar la consulta SQL ejecutada utilizando filtros como posts_clauses u otros similares. Para encontrarlos, busca posts_clauses en "wp-includes/query.php" y observa la serie de filtros justo antes de esta línea. Juntos, son capaces de personalizar cualquier parte de la consulta.

Otra cosa que puedes hacer es fusionar manualmente los posts consultados en los objetos

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

// comenzar a colocar los contenidos en el nuevo objeto
$result->posts = array_merge( $photos_query->posts, $quotes_query->posts );

// aquí quizás quieras aplicar algún tipo de ordenamiento a $result->posts

// también necesitamos establecer el conteo de posts correctamente para habilitar el bucle
$result->post_count = count( $result->posts );
5 nov 2012 10:04:00
Comentarios

¡Tu segunda solución (sin el SQL) funcionó! Ahora tengo control total sobre lo que va a la consulta final antes de entrar en el bucle. Gracias por tu ayuda.

Andy Merskin Andy Merskin
5 nov 2012 10:34:46

La primera es difícil pero más eficiente (en la segunda todavía hay 2 consultas a la base de datos). Diría que depende de la preferencia personal.

Mridul Aggarwal Mridul Aggarwal
5 nov 2012 10:54:14

¡Estaría extremadamente interesado en una forma de lograr la primera solución! Los filtros necesarios, etc. ¿Esto requiere un UNION de algún tipo en el SQL para cada post_type?

Solomon Closson Solomon Closson
28 oct 2017 01:07:08

@SolomonClosson este filtro puede ayudar - https://codex.wordpress.org/Plugin_API/Filter_Reference/posts_clauses

Mridul Aggarwal Mridul Aggarwal
30 oct 2017 15:45:51

Gracias por esto. Ayuda mucho. Debería ser más obvio en la documentación principal de WP.

Khom Nazid Khom Nazid
10 abr 2022 18:29:46
0

@mridual aggarwal tu respuesta es muy muy buena pero desafortunadamente no está combinando realmente los 2 wp_query, solo muestra los posts de ambos ordenados, quiero decir 5 posts del primero y 5 del segundo pero no todos ordenados juntos en uno. Así que tengo esta solución y logra exactamente el objetivo, al menos para mí.

<?php
$term = get_term_by( 'slug', get_query_var( 'tag' ), "post_tag" );
$tagslug = $term->slug;
$post_types = get_post_types('','names');
?>
<?php
//primera consulta
$blogposts = get_posts(array(
    'tag' => $tagslug, //primera taxonomía
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
//segunda consulta
$authorposts = get_posts(array(
    'bookauthor' => $tagslug, //segunda taxonomía
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
$mergedposts = array_merge( $blogposts, $authorposts ); //combinar consultas

$postids = array();
foreach( $mergedposts as $item ) {
$postids[]=$item->ID; //crear una nueva consulta solo con los IDs de los posts
}
$uniqueposts = array_unique($postids); //eliminar IDs de posts duplicados

$posts = get_posts(array(
        //nueva consulta solo con los IDs únicos de las consultas combinadas anteriores
    'post__in' => $uniqueposts,  
    'post_type' => $post_types,
    'post_status' => 'publish',
    ));
foreach( $posts as $post ) :
setup_postdata($post);
?>
// diseño de los posts
<?php endforeach; ?>
<?php wp_reset_postdata();?>
28 oct 2013 15:26:29