Combinarea interogărilor cu argumente diferite per tip de postare
Construiesc o secțiune pe un site unde combin două tipuri diferite de postări într-o singură buclă și le afișez aleatoriu. Problema este că îmi este dificil să găsesc o modalitate de a limita numărul de postări per tip.
Iată ce am încercat:
O interogare cu mai multe tipuri de postări poate fi realizată cu un array:
$args = array( 'post_type' => array( 'photos', 'quotes' ), ...
... dar nu poate fi limitată la un anumit număr de postări per tip.
Combinarea a două array-uri de argumente pentru interogare înainte de a rula 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; // Am încercat și array_merge( $photos, $quotes );
Fără succes. Ce se întâmplă este că variabila ulterioară
$quotes
suprascrie$photos
și afișează doar citatele.Combinarea a două obiecte WP_Query împreună prin typecast:
$photos_query = new WP_Query( $photos ); $quotes_query = new WP_Query( $quotes ); $result = (object)array_merge( (array)$photos_query, (array)$quotes_query );
... și așa mai departe.
Probabil aș putea folosi o interogare SQL direct în baza de date, dar trebuie să pot combina aceste două tipuri separate de postări într-o singură buclă, aranjate aleatoriu ȘI limitate la un anumit număr de postări per tip.
Mulțumesc pentru ajutor!

O metodă este de a personaliza interogarea SQL executată folosind filtre precum posts_clauses
sau altele asemănătoare. Pentru a le găsi, caută posts_clauses
în fișierul "wp-includes/query.php" și vezi seria de filtre situate chiar înaintea acestei linii. Împreună, acestea sunt capabile să personalizeze orice parte a interogării.
Un alt lucru pe care îl poți face este să îmbini manual postările interogate în obiecte
$photos_query = new WP_Query( $photos );
$quotes_query = new WP_Query( $quotes );
$result = new WP_Query();
// începe să adaugi conținutul în noul obiect
$result->posts = array_merge( $photos_query->posts, $quotes_query->posts );
// aici ai putea să aplici o formă de sortare pe $result->posts
// trebuie să setăm corect numărul de postări pentru a permite iterarea
$result->post_count = count( $result->posts );

A doua ta soluție (fără SQL) a funcționat! Acum am control complet asupra a ceea ce intră în acea interogare finală înainte de a intra în buclă. Mulțumesc pentru ajutor!

Prima este dificilă dar mai eficientă (în a doua sunt încă 2 interogări la baza de date). Aș spune că depinde de preferințele personale.

Aș fi extrem de interesat de o metodă de a realiza prima soluție! Filtrele necesare, etc. Necesită un UNION
de un fel în SQL pentru fiecare post_type?

@SolomonClosson acest filtru poate ajuta - https://codex.wordpress.org/Plugin_API/Filter_Reference/posts_clauses

@mridual aggarwal răspunsul tău este foarte bun, dar din păcate nu combină cu adevărat cele 2 interogări wp_query
. Acesta doar afișează postările din ambele în ordine, adică 5 postări din prima și 5 din a doua, dar nu sunt sortate toate împreună. Așadar, am această soluție care exact a atins scopul pentru mine, cel puțin.
<?php
$term = get_term_by( 'slug', get_query_var( 'tag' ), "post_tag" );
$tagslug = $term->slug;
$post_types = get_post_types('','names');
?>
<?php
// prima interogare
$blogposts = get_posts(array(
'tag' => $tagslug, // prima taxonomie
'post_type' => $post_types,
'post_status' => 'publish',
));
// a doua interogare
$authorposts = get_posts(array(
'bookauthor' => $tagslug, // a doua taxonomie
'post_type' => $post_types,
'post_status' => 'publish',
));
$mergedposts = array_merge( $blogposts, $authorposts ); // combină interogările
$postids = array();
foreach( $mergedposts as $item ) {
$postids[]=$item->ID; // creează o nouă interogare doar cu ID-urile postărilor
}
$uniqueposts = array_unique($postids); // elimină ID-urile duplicate
$posts = get_posts(array(
// noua interogare doar cu ID-urile unice din interogările combinate de mai sus
'post__in' => $uniqueposts,
'post_type' => $post_types,
'post_status' => 'publish',
));
foreach( $posts as $post ) :
setup_postdata($post);
?>
// layout-ul postărilor
<?php endforeach; ?>
<?php wp_reset_postdata();?>
