Obține toate sub-paginile părinte folosind WP Query
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

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 );
?>

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ă?

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

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.

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ă

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.

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;

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

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
}
