Obține toate sub-paginile părinte folosind WP Query

30 nov. 2011, 12:57:46
Vizualizări: 37.7K
Voturi: 15

Iată codul meu

$my_wp_query = new WP_Query();
$all_wp_pages = $my_wp_query->query(array('post_type' => 'page','post_parent'=>$parid,'orderby'=>'title','order'=>'ASC' ));

Acesta afișează doar sub-paginile de primul nivel. Am nevoie de toate sub-paginile, sub-paginile sub-paginilor... și toate celelalte. Am căutat o soluție și pot obține toate sub-paginile folosind get_pages și wp_list_pages.

Dar am într-adevăr nevoie să sortez ordinea după o valoare meta personalizată a postării. Așa că trebuie să folosesc o interogare personalizată.

Vă rog să mă ajutați. Mulțumesc

2
Comentarii

Mai jos spui că ai găsit un răspuns, care este acesta?

Drew Baker Drew Baker
17 aug. 2012 21:41:18

Ai verificat funcția get_page_children?

t31os t31os
13 apr. 2013 16:17:47
Toate răspunsurile la întrebare 6
5

De ce să nu folosești pur și simplu get_pages()?

De exemplu:

<?php
// Determină ID-ul paginii părinte
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Obține paginile copil ca un array
$page_tree_array = get_pages( array(
    'child_of' => $parent_page_id;
) );
?>

Dar dacă trebuie neapărat să fie un obiect WP_Query(), folosește o metodă similară:

<?php
// Determină ID-ul paginii părinte
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Construiește array-ul de argumente pentru WP_Query()
$page_tree_query_args = array(
    'post_parent' => $parent_page_id;
);
// Obține paginile copil ca un obiect WP_Query()
$page_tree_query = new WP_Query( $page_tree_query_args );
?>
30 nov. 2011 19:22:11
Comentarii

Dacă folosim funcționalitatea get_pages(), nu am putea implementa sortarea (sort_column) pentru câmpurile personalizate. Aceasta acceptă doar câmpurile din tabelul post. Am nevoie să implementez sortarea pentru câmpuri personalizate. De aceea am folosit wp_query(). Există vreo altă metodă alternativă?

phpuser phpuser
1 dec. 2011 06:07:29

Ai văzut a doua jumătate a răspunsului meu, unde folosesc WP_Query()?

Chip Bennett Chip Bennett
1 dec. 2011 15:59:53

Am încercat acest cod, dar returnează doar subpagini de nivelul întâi. Am nevoie de subpagini >> sub-subpagini >> etc... (mai multe niveluri inferioare de pagini). În sfârșit, am găsit soluția. Mulțumesc pentru răspunsul tău.

phpuser phpuser
3 dec. 2011 07:15:48

care este soluția ta!?

JCHASE11 JCHASE11
11 mar. 2013 22:12:57

Există câteva puncte și virgule în interiorul definițiilor de array de mai sus care provoacă erori de sintaxă.

ptrin ptrin
22 ian. 2014 05:49:11
0

Problema

Ceea ce nu înțelegi este "Cum fac X?". Aceasta nu este o acțiune într-un singur pas, ci un proces în mai mulți pași și trebuie descompus.

Nu trebuie să faci asta:

obține toate articolele care sunt copii ai X ordonate după meta

Trebuie să faci asta:

obține toate articolele care sunt copii ai X
    pentru fiecare copil, obține toate articolele care sunt copii
        pentru fiecare copil al acelui copil, obține toate articolele care sunt copii
            ...
                hmmm nu mai avem copii rămași

Ia lista noastră de articole și ordonează-le după meta

Soluția Generală

Deci, pentru a înțelege cum să faci asta la infinit până când ajungi la capăt, fără să o hardcodezi, trebuie să înțelegi funcțiile recursive.

exemplu:

function make_zero( $amount ) {
    $amount = $amount - 1;
    if ( $amount > 1 ){
        return make_zero( $amount );
    }
    return $amount;
}

Aplicarea Recursiei la Această Problemă pentru o Soluție

Deci părintele tău este $parid, iar meta-ul articolului tău are o cheie $metakey.

Să-l pasăm într-o funcție pentru a obține copiii săi.

$children = get_children_with_meta( $parid, $metakey );

Apoi vom sorta array-ul $children, cheile vor fi ID-urile articolelor, iar valorile vor fi valorile meta.

asort($children);

și să definim funcția astfel:

function get_children_with_meta( $parent_id, $metakey ) {
    $q = new WP_Query( array( 'post_parent' => $parent_id, 'meta_key' => $metakey ));
    if ( $q->have_posts() ) {
        $children - array();
        while ( $q->have_posts() ) {
            $q->the_post();
            $meta_value = get_post_meta(get_the_ID(), $metakey, true );
            $children[get_the_ID() ] = $meta_value;
        }
        return $children;
    } else {
        // nu există copii!!
        return array();
    }
}

Aceasta îți oferă un array de ID-uri de articole și valori, ordonate de la cel mai mic la cel mai mare. Poți folosi alte funcții PHP de sortare pentru a le ordona de la cel mai mare la cel mai mic.

Dar Cum Rămâne cu Copiii Copiilor?

În mijlocul buclei noastre, trebuie să facem un apel recursiv, pasând ID-ul copilului în loc de ID-ul părintelui.

Deci asta:

$q->the_post();
$meta_value = get_post_meta(get_the_ID(), $metakey, true );
$children[get_the_ID() ] = $meta_value;

Devine asta:

$q->the_post();
$meta_value = get_post_meta(get_the_ID(), $metakey, true );
$children[get_the_ID() ] = $meta_value;

// acum obține copiii copiilor
$grandchildren = get_children_with_meta( get_the_ID(), $metakey );

// combină nepoții și copiii în aceeași listă
$children = array_merge( $children, $grandchildren );

Cu această modificare, funcția acum obține copiii, copiii copiilor, copiii copiilor copiilor..... etc.

La final poți elimina valorile din array pentru a obține doar ID-uri astfel:

$post_ids = array_keys( $children );
$q = new WP_Query( array( 'post__in' => $post_ids );
// etc

Folosind această strategie, poți înlocui valoarea cheii meta cu orice altă metrică sau poți folosi funcții recursive în alte moduri.

Deoarece codul complet necesită doar câteva secunde de înțelegere de bază și un copy paste rapid, nu voi insulta inteligența ta cu un bloc complet de cod de copiat.

Avantaje

  • Cu modificări, funcționează pentru orice tip de articol și formă de date
  • Poate fi modificat pentru a genera markup imbricat
  • Ușor de cache-uit pentru a accelera prin stocarea array-urilor returnate în transiente
  • Poate fi configurat cu paginare prin aplicarea paginării la WP_Query final

Probleme pe Care Le Vei Întâmpina

  • Nu ai cum să știi câți copii există până nu i-ai găsit, deci costurile de performanță nu se scalează
  • Ceea ce dorești va genera multe interogări și este inerent costisitor din cauza adâncimilor potențiale implicate.

Recomandarea Mea

Aș recomanda fie să aplatizezi ierarhia paginilor, fie să folosești o taxonomie în schimb. De exemplu, dacă evaluezi articole, ai o taxonomie "Rating Articol" cu termenii 1,2,3,4 și 5 etc. Acest lucru îți va oferi o listă de articole din cutie.

Alternativ, folosește meniuri de navigare și ocolește complet această problemă

19 apr. 2013 17:46:12
0

Obține recursiv toate subpaginile curente

Iată o abordare recursivă folosind get_children. Puneți următoarele în fișierul dumneavoastră functions.php:

function get_all_subpages($page, $args = '', $output = OBJECT) {
    // Validează parametrul 'page'
    if (! is_numeric($page))
        $page = 0;

    // Setează argumentele
    $default_args = array(
        'post_type' => 'page',
    );
    if (empty($args))
        $args = array();
    elseif (! is_array($args))
        if (is_string($args))
            parse_str($args, $args);
        else
            $args = array();
    $args = array_merge($default_args, $args);
    $args['post_parent'] = $page;

    // Validează parametrul 'output'
    $valid_output = array(OBJECT, ARRAY_A, ARRAY_N);
    if (! in_array($output, $valid_output))
        $output = OBJECT;

    // Obține copiii
    $subpages = array();
    $children = get_children($args, $output);
    foreach ($children as $child) {
        $subpages[] = $child;

        if (OBJECT === $output)
            $page = $child->ID;
        elseif (ARRAY_A === $output)
            $page = $child['ID'];
        else
            $page = $child[0];

        // Obține subpaginile prin recursivitate
        $subpages = array_merge($subpages, get_all_subpages($page, $args, $output));
    }

    return $subpages;
}

Cum să-l folosești

Folosește funcția de mai sus oriunde dorești, de exemplu astfel:

$all_current_subpages = get_all_subpages(0);

Funcția acceptă un parametru args (șir de interogare sau array) și un tip de output (vezi mai sus).

Deci ai putea să o folosești și astfel:

$args = array(
    'post_status' => 'private',
    'order_by' => 'post_date',
    'order' => 'DESC',
);
$all_current_subpages = get_all_subpages(42, $args, ARRAY_A);

Și datorită dependenței get_children => get_posts => WP_Query poți folosi valori meta, așa cum a cerut inițial autorul acestei întrebări.

14 apr. 2013 04:22:48
0

Am creat o funcție recursivă care obține toate ID-urile copiilor unei pagini părinte. După ce avem ID-urile, facem o interogare pentru pagini și putem ordona rezultatele după cheie/valoare meta.

// Obține toate ID-urile copiilor unui post_parent
function _get_children_ids( $post_parent ) {
    $results = new WP_Query( array(
        'post_type' => 'page',
        'post_parent' => $post_parent
    ) );

    $child_ids = array();
    if ( $results->found_posts > 0 )
        foreach ( $results->posts as $post ) // adaugă fiecare ID copil în array
            $child_ids[] = $post->ID;

    if ( ! empty( $child_ids ) )
        foreach ( $child_ids as $child_id ) // adaugă copii suplimentari în array
            $child_ids = array_merge( $child_ids, _get_children_ids( $child_id ) );

    return $child_ids;
}

$children_ids = _get_children_ids( 9 ); // folosește ID-ul numeric al paginii sau get_the_id()

$results = new WP_Query( array(
    'post_type'   => 'page',
    'post__in'   => $children_ids
    #'meta_key'   => 'meta_key', // cheia ta meta
    #'orderby'    => 'meta_key',
    /* 'meta_query' => array( // interogare meta opțională
        array(
            'key' => 'meta_key', // cheie
            'value' => array(3, 4), // valori
            'compare' => 'IN', // operator
        )
    ) */
) );

var_dump( $results );

Dacă trebuie să sortezi copiii după cheie/valoare meta într-o manieră ierarhică, ar trebui să transmiți valorile meta_key și order_by către WP_Query în funcția _get_children_ids (în loc de WP_Query final).

Dacă nu, o metodă mai simplă de a obține toate ID-urile copiilor este:

$children = get_pages( 'child_of=9');

$children_ids = array();
if ( ! empty( $children ) )
    foreach ( $children as $post )
        $children_ids[] = $post->ID;
18 apr. 2013 12:08:52
0

Nu sunt sigur că exact asta cauți, dar ai putea folosi funcția wp_list_pages și parametrii 'child_of' și 'depth'.

Consultă următoarea pagină din Codex pentru mai multe informații: http://codex.wordpress.org/Function_Reference/wp_list_pages

30 nov. 2011 16:58:57
1
-2

FAC ASTA SĂ FUNCȚIONEZE, DOAR COPIAZĂ ȘI LIPSEȘTE CODUL ÎN FIȘIERUL TĂU PAGE.PHP

//REDIRECTEAZĂ CĂTRE PRIMA PAGINĂ COPIL DIN PAGINA PĂRINTE

// Construiește array-ul de argumente pentru WP_Query()
$page_tree_query_args = array(
    'post_parent' => $post -> ID, // ID-ul paginii curente
    'post_type' => 'page',       // Tipul postării - pagină
    'order' => 'asc'             // Ordinea ascendentă
);
// Obține paginile copil ca obiect WP_Query()
$page_tree_query = new WP_Query( $page_tree_query_args );
if(!empty($page_tree_query -> posts)){
    $first_subpage = $page_tree_query -> posts[0] -> ID; // ID-ul primei pagini copil
    wp_redirect( get_permalink( $first_subpage ) );      // Redirecționează către prima pagină copil
    exit;                                               // Oprește execuția scriptului
}
26 sept. 2013 14:36:14
Comentarii

Aceasta este A) nu funcționează ($post -> ID?), B) nu este ceea ce s-a cerut, C) nu este explicat prea bine.

tfrommen tfrommen
26 sept. 2013 14:58:00