Cum să obții toți copiii și nepoții unui tip de postare personalizată ierarhică?

15 ian. 2013, 14:33:57
Vizualizări: 18.8K
Voturi: 9

Am nevoie să obțin toate postările copil pentru un anumit ID de părinte (rădăcină).

get_posts( array( 'numberposts' => -1, 'post_status' => 'publish', 'post_type' => 'microsite', 'post_parent' => $root_parent_id, 'suppress_filters' => false ) );

WP-Codex: funcția get_post() are parametrul post_parent dar nu are child_of.

Avantajul funcției get_pages() în combinație cu parametrul child_of este "... Reține că parametrul child_of va returna atât 'nepoții' ID-ului dat, nu doar descendenții direcți."*

0
Toate răspunsurile la întrebare 5
2
13

Va trebui să parcurgeți aceste articole și apoi să faceți mai multe interogări pentru fiecare articol, repetând până când nu găsiți articole într-o interogare.

de exemplu:

function get_posts_children($parent_id){
    $children = array();
    // preluăm copiii articolelor
    $posts = get_posts( array( 'numberposts' => -1, 'post_status' => 'publish', 'post_type' => 'microsite', 'post_parent' => $parent_id, 'suppress_filters' => false ));
    // acum preluăm nepoții
    foreach( $posts as $child ){
        // recursivitate!! ura
        $gchildren = get_posts_children($child->ID);
        // îmbinăm nepoții în array-ul copiilor
        if( !empty($gchildren) ) {
            $children = array_merge($children, $gchildren);
        }
    }
    // îmbinăm descendenții direcți pe care i-am găsit mai devreme
    $children = array_merge($children,$posts);
    return $children;
}

// exemplu de utilizare a funcției de mai sus, să o apelăm și să afișăm rezultatele
$descendants = get_posts_children($post->ID);
echo '<pre>';
print_r($descendants);
echo '</pre>';

Da, funcția de mai sus se autoapelează, este o funcție recursivă. Va continua să se autoapeleze până când ajunge la un punct în care articolul analizat nu are copii, apoi se va întoarce fără să se mai autoapeleze, iar întregul stack se va reconstrui înapoi construind array-ul de copii. Ar fi bine să faceți cercetări suplimentare în acest domeniu.

Rețineți că există un cost inerent la ceea ce doriți, indiferent dacă utilizați funcții recursive sau nu, care este legat de câte niveluri de articole aveți. 5 niveluri de articole vor fi mai costisitoare decât 2, iar scalarea nu este liniară. Ați putea dori să utilizați transiente pentru a stoca în cache rezultatul, în funcție de cum implementați acest lucru.

Un alt mod de a reduce costul este prin a analiza arborele de articole doar până la un anumit număr de niveluri, de exemplu nepoți dar nu strănepoți. Acest lucru se poate face prin transmiterea unui parametru de adâncime și decrementarea acestuia la fiecare apel recursiv, asigurându-vă că returnați un array gol la început dacă adâncimea este 0 sau mai mică. Multe tutoriale despre funcții recursive folosesc acest lucru ca exemplu.

15 ian. 2013 15:00:37
Comentarii

Problema cu acest cod este că nu oferă ordonarea corectă; primesc toate elementele de nivel superior mai întâi, apoi toate cele de al doilea nivel într-un singur array aplatizat. Aveți vreo idee despre cum să rezolv asta?

dama_do_bling dama_do_bling
9 apr. 2015 00:23:12

Acest cod nu a fost conceput să facă asta, ai o problemă diferită care necesită o soluție ușor diferită și o bună doză de context

Tom J Nowell Tom J Nowell
9 apr. 2015 03:38:38
1

Am avut o cerință similară, dar trebuia să păstrez ierarhia, așa că răspunsul lui Tom mi-a dat un punct de plecare:

function get_post_offspring($post)
{
    // Funcție pentru a parcurge programatic descendenții unui post

    // Obține copiii imediați ai postului curent
    // și îi adaugă într-un element de obiect numit children
    $post->children = get_children(array("post_parent" => $post->ID, "post_type" => "page", "post_status" => "publish"));
    
    // dacă postul nu are copii, returnează postul cu
    // children ca fiind un array gol
    if (empty($post->children)) {
        return $post;
    }
    foreach ($post->children as $child) {
        // Pentru fiecare copil al acestui post... obține copiii
        $children = get_children(array("post_parent" => $child->ID, "post_type" => "page", "post_status" => "publish"));
        if (!empty($children)) {
            // dacă acest post are copii... atunci apelează această funcție din nou
            // pentru a atribui elementul children acestui post și a parcurge mai departe
            // descendenții acestui post

            $child = get_post_offspring($child);
        }
    }

    return $post;
}

De asemenea, aveam nevoie să parcurg lista cu un <ul> păstrând ordinea și nivelul.

function render_list_items($children)
{
    foreach ($children as $child) {
        $has_children = !empty($child->children);

        echo "<li>";
        echo "<a href='" . get_permalink($child) . "'>" . $child->post_title . "</a";
        if ($has_children) {
            // Dacă postul are copii, creează un nou <ul> în interiorul <li>-ului curent
            // și apelează funcția din nou
            echo "<ul>";
            echo render_list_items($child->children);
            echo "</ul>";
        }

        echo "</li>";
    }

}

Pentru a pune totul la un loc, am ceva de genul:

global $post;

$post_id = $post->ID;

// Obține strămoșii postului curent, unde ultimul element din array
// este părintele cel mai de sus
$ancestors = get_post_ancestors($post->ID);

$root_id = array_pop($ancestors);
// Acum avem postul rădăcină al acestui post și coborâm pentru a obține toți descendenții săi
$root_post = get_post($root_id);

$root_children = get_post_offspring($root_post);
23 iul. 2021 16:05:53
Comentarii

echo "<a href='" . get_permalink($child) . "'>" . $child->post_title . "</a";

lipsește caracterul > de închidere pentru tag-ul ahref

Dar în rest răspuns excelent, mulțumesc!

Lemon Bacon Lemon Bacon
25 sept. 2022 19:29:16
1

Pur și simplu folosește get_page_children(). Funcționează pentru orice tip de postare (nu doar pagini) și este practic ceea ce @TomJNowell a arătat în cealaltă întrebare, dar deja implementat în nucleul WordPress.

$children = get_page_children( $post->ID, $GLOBALS['wp_query'] );

Exemplul de mai sus este ca în Codex. De aceea poți lua pur și simplu obiectul global de interogare (sau orice alt obiect de interogare) pentru a fi folosit ca bază de căutare.

23 sept. 2013 14:14:09
Comentarii

Dar cum folosești asta pentru un alt tip de postare? Nu reușesc să funcționeze.

dama_do_bling dama_do_bling
9 apr. 2015 00:18:30
0

Folosiți următorul shortcode pentru a afișa toți copiii și nepoții într-o vedere ierarhică. Utilizare: [my_children_list] sau [my_children_list page_id=123]

function my_children_list_func($atts, $content = null) {
    global $post;

    $a = shortcode_atts( array(
            'page_id' => ''
    ), $atts );

    $args = array( 
            'numberposts' => -1, 
            'post_status' => 'publish', 
            'post_type' => 'microsite', 
            'post_parent' => (isset($a['page_id']) && $a['page_id']) ? $a['page_id'] : $post->ID,
            'suppress_filters' => false 
    );

    $parent = new WP_Query( $args );

    ob_start();

    if ( $parent->have_posts() ) :?>
            <ul>
            <?php while ( $parent->have_posts() ) : $parent->the_post(); ?>
                    <li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
                    <?php echo do_shortcode('[tadam_children_list page_id='.get_the_ID().']') ?>
                    </li>
            <?php endwhile;?>
            </ul>
    <?php endif; wp_reset_postdata();

    return ob_get_clean();
}
add_shortcode( 'my_children_list', 'my_children_list_func' );
31 dec. 2018 11:22:10
0

Doar în cazul în care cineva dă peste acest lucru și decide să implementeze răspunsul ales, get_pages() funcționează atât cu pagini, cât și cu tipuri de postări ierarhice. Prin urmare, puteți folosi pur și simplu get_pages() cu parametrul child_of.

8 iun. 2020 14:53:26