Combinarea interogărilor cu argumente diferite per tip de postare

5 nov. 2012, 09:31:58
Vizualizări: 32.1K
Voturi: 16

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!

0
Toate răspunsurile la întrebare 2
5
21

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 );
5 nov. 2012 10:04:00
Comentarii

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!

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

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.

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

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?

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

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

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

Mulțumesc pentru asta. Ajută foarte mult. Ar trebui să fie mai evident în documentația principală WP.

Khom Nazid Khom Nazid
10 apr. 2022 18:29:46
0

@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();?>
28 oct. 2013 15:26:29