¿Puedo fusionar 2 WP_Query($variable)?
Estoy ejecutando una red multisite y he configurado una consulta SQL que usa switch_to_blog(); y consulta los posts.
¿Hay alguna manera de que pueda declarar la consulta dentro de un nuevo WP_Query y realmente fusionarla con otra?
Básicamente si hago esto:
$number1 = new WP_Query($multisitequery);
¿Puedo fusionarlo con:
$number2 = new WP_Query($normalquery);
$normalquery
contiene configuraciones como paginación, por página, extracto, título, etc... en un shortcode de portfolio.
Me gustaría que incluyera posts consultados desde mi nueva consulta $multisite
.
¿Se puede lograr esto? Solo quiero evitar crear toda una nueva configuración de shortcode jaja
Muchas gracias de antemano. Rory
EDICIÓN========
Lo que tengo es:
$portfolio = array();
$portfolio = $settings;
Más abajo en mi función de portfolio "después de todas las $settings['options']" tengo:
$portfolio_query = new WP_Query( $portfolio );
El $portfolio_query
usa un bucle en una plantilla de página.
Quiero agregar una consulta adicional así:
global $wpdb, $blog_id, $post;
$blogs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM wp_blogs ORDER BY blog_id" ) );
$globalcontainer = array();
foreach ($blogs as $blog){
// Cambiar al blog
switch_to_blog($blog->blog_id);
$globalquery = query_posts($args);
$globalcontainer = array_merge( $globalcontainer, $globalquery );
// Restaurar al blog actual
restore_current_blog();
}
donde asumo que $globalcontainer
sería el array para fusionar en el wp_query();
.
Entonces, tomando en cuenta lo que has respondido, en teoría podría simplemente:
$mergedqueryargs = array_merge($portfolio , $globalcontainer);
$portfolio_query = new WP_query($mergedqueryargs);
¿Sería eso correcto?
Segundo, con respecto a la sobrescritura de claves del array_merge..... ¿Cómo podría evitar una sobrescritura?
No basta con fusionar los argumentos, necesitas fusionar el array resultante de posts y el conteo de post_count. Esto es lo que me funciona:
//configura tus consultas como ya lo haces
$query1 = new WP_Query($args_for_query1);
$query2 = new WP_Query($args_for_query2);
//crea una nueva consulta vacía y rellénala con las dos anteriores
$wp_query = new WP_Query();
$wp_query->posts = array_merge( $query1->posts, $query2->posts );
//rellena el conteo de post_count para que el bucle funcione correctamente
$wp_query->post_count = $query1->post_count + $query2->post_count;

Esto se ve bien, pero estoy buscando una solución que pueda usarse con el hook pre_get_posts - es decir, necesito modificar un objeto WP_Query existente. He intentado usar '$wp_query->init();' en lugar de '$wp_query = new WP_Query();', pero eso parece causar problemas. ¿Alguna sugerencia?

Deberías agregar una pregunta diferente ya que es una respuesta distinta, pero puedes usar este mismo código pero solo las partes de query2, modificando las partes ->posts y ->post_count del objeto $wp_query para tener la suma de la consulta original que te da pre_get_posts y la segunda consulta que quieres añadir.

Gracias por esto. Tenía un meta_query problemático usando una relación OR. Lo dividí usando esta técnica y pasó de 41s a 0.01s.

@ban-geoengineering ¿Alguna vez lograste resolver esto? Estoy atascado con lo mismo.

@harvey Lo siento, no encuentro ningún código relacionado con eso. (Fue hace unos años). Tu mejor opción podría ser publicar una nueva pregunta. Buena suerte. :-)

Si terminas creando un nuevo array y eliminando duplicados usando algo como array_unique()
, deberías poder poblar $wp_query->post_count
con count($wp_query->posts)

Generalmente fusiono sus arrays de IDs y hago una tercera consulta. Para mantener las primeras consultas ligeras, solo devuelvo sus IDs usando el parámetro fields así:
//configura tus consultas con el parámetro extra fields => ids
$query1 = new WP_Query(array('fields' => 'ids','other_parameters' => 'etc'));
$query2 = new WP_Query(array('fields' => 'ids','other_parameters'=>'etc'));
//ahora tienes los IDs de posts en $query->posts
$allTheIDs = array_merge($query1->posts,$query2->posts);
//nueva consulta, usando el parámetro post__in
$finalQuery = new WP_Query(array('post__in' => $allTheIDs));
Espero que esto ayude
---EDITADO---
Después de mi respuesta, la pregunta original fue editada con detalles sobre multisitio. En el caso de fusiones de posts en multisitio, esto no funciona.

Esta respuesta funciona bien y parece menos un truco que la solución principal. La usé hace un año más o menos y volví a utilizarla ahora. Gracias.

¿Cómo puede funcionar esto correctamente cuando los post_ID no son únicos en el ámbito multisitio (son únicos por blog, pero varios posts pueden tener los mismos ID en toda la red)?

@Adal La pregunta original fue editada después de mi respuesta, por lo que mi respuesta es relevante para el ámbito de un solo sitio. Con multisitio nunca intenté fusionar consultas y en ese caso obviamente esto no funcionará, las consultas deben hacerse por separado y luego fusionarse. Después de la fusión podrías intentar ordenarlas con funciones de ordenamiento de php (ordenar por fecha de publicación, etc.).

Puedes preservar el ordenamiento usando 'orderby' => 'post__in'
en la última consulta.

Esto solo funciona para mí cuando establezco el post_type en el $finalQuery

para custom post types, creo que el parámetro post_type lo necesita en cualquier caso, incluso cuando se pregunta por ids porque es post_type=post por defecto @RobbTe

Asegúrate de verificar si el array de IDs fusionados está vacío. Porque una consulta post__in devuelve resultados si es un array vacío. Un error que WP se niega a corregir: https://core.trac.wordpress.org/ticket/28099

Entonces, si tienes esto:
$number1 = new WP_Query($multisitequery);
$number2 = new WP_Query($normalquery);
Asumo que defines estos en algún lugar anterior?
$multisitequery = array();
$normalquery = array();
...en cuyo caso, para combinar las dos consultas, solo necesitas array_merge()
los dos arrays antes de pasarlos a new WP_Query()
:
$merged_query_args = array_merge( $normalquery, $multisitequery );
$merged_query = new WP_Query( $merged_query_args );
Nota que el orden es importante en la llamada a array_merge()
. Si ambos tienen la misma clave de array, el segundo array sobrescribirá al primero.

De esta manera, puedes combinar dos consultas WP_Query con diferentes post_type u otros datos de ordenación, por ejemplo, y luego unirlas por ids en una sola consulta WP_Query que funcionará completamente - para preservar el orden al unirlas, necesitas especificar orderby => post__in
Mi ejemplo muestra cómo crea un nuevo ciclo WP_Query y puede afectar cualquier otro ciclo para mostrar publicaciones al llamar new global_change_of_sorting_posts->change_query_posts() => query_posts() ¡debes llamar esto antes de procesar el ciclo para mostrar las publicaciones!
class global_change_of_sorting_posts
{
public function get_posts_ids()
{
$query1 = new WP_Query([
'fields' => 'ids',
'posts_per_page' => -1,
'post_type' => 'post',
]);
$query2 = new WP_Query([
'posts_per_page' => -1,
'fields' => 'ids',
'post_type' => 'custom-post',
]);
$merge_ids_posts = $query1->posts + $query2->posts;
wp_reset_query();
return $merge_ids_posts;
}
public function get_posts_wp_query()
{
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$posts_per_page = 40;
$wp_query = new WP_Query([
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'post__in' => $this->get_posts_ids(),
'orderby' => 'post__in',
]);
while ($wp_query->have_posts()) {
$wp_query->the_post();
var_dump(get_the_ID());
}
}
public function change_query_posts($query_string)
{
parse_str($query_string, $args);
$args['post__in'] = $this->get_posts_ids();
$args['orderby'] = 'post__in';
query_posts($args); # conversión de la consulta
}
}
