Obtener todas las subpáginas del padre usando wp query

30 nov 2011, 12:57:46
Vistas: 37.7K
Votos: 15

Aquí está mi código

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

Esto muestra solo las subpáginas del primer nivel. Necesito todas las subpáginas, las subpáginas de las subpáginas... y todas. He buscado una solución y puedo obtener todas las subpáginas usando get_pages y wp_list_pages.

Pero realmente necesito ordenar por valor de meta personalizado. Así que tengo que usar una consulta personalizada.

Por favor ayuda. Gracias

2
Comentarios

Abajo mencionas que encontraste una respuesta, ¿cuál es?

Drew Baker Drew Baker
17 ago 2012 21:41:18

¿Has revisado get_page_children?

t31os t31os
13 abr 2013 16:17:47
Todas las respuestas a la pregunta 6
5

¿Por qué no simplemente usar get_pages()?

Por ejemplo:

<?php
// Determinar el ID de la página padre
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Obtener páginas hijas como un array
$page_tree_array = get_pages( array(
    'child_of' => $parent_page_id;
) );
?>

Pero si realmente debe ser un objeto WP_Query(), usa un método similar:

<?php
// Determinar el ID de la página padre
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Construir el array de argumentos para WP_Query()
$page_tree_query_args = array(
    'post_parent' => $parent_page_id;
);
// Obtener páginas hijas como objeto WP_Query()
$page_tree_query = new WP_Query( $page_tree_query_args );
?>
30 nov 2011 19:22:11
Comentarios

Si usamos la funcionalidad get_pages() no podríamos implementar el ordenamiento (sort_column) para campos personalizados. Solo acepta campos de la tabla de posts. Necesito implementar el ordenamiento para campos personalizados. Por eso usé wp_query(). ¿Hay alguna alternativa?

phpuser phpuser
1 dic 2011 06:07:29

¿Viste la segunda parte de mi respuesta, donde uso WP_Query()?

Chip Bennett Chip Bennett
1 dic 2011 15:59:53

Probé este código pero solo devuelve las subpáginas de primer nivel. Necesito subpágina >> sub de sub >> etc... (múltiples niveles inferiores de páginas). Finalmente encontré la solución. Gracias por tu respuesta

phpuser phpuser
3 dic 2011 07:15:48

¿cuál es tu solución!?

JCHASE11 JCHASE11
11 mar 2013 22:12:57

Hay algunos puntos y comas dentro de las definiciones de arreglos anteriores que están causando errores de sintaxis.

ptrin ptrin
22 ene 2014 05:49:11
0

El Problema

Lo que te está costando entender es "¿Cómo hago X?" Esto no es una acción de un solo paso, es un proceso de múltiples pasos y necesita ser desglosado.

No necesitas hacer esto:

obtener todos los posts que son hijos de X ordenados por meta

Necesitas hacer esto:

obtener todos los posts que son hijos de X
    para cada hijo, obtener todos los posts que son hijos
        para cada hijo de ese hijo obtener todos los posts que son hijos
            ...
                hmmm ya no nos quedan más hijos

Tomar nuestra lista de posts y ordenarlos por meta

La Solución General

Entonces, para entender cómo hacerlo infinitamente hasta llegar al final, sin codificarlo manualmente, necesitas comprender las funciones recursivas.

ejemplo:

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

Aplicando Recursión a Este Problema para una Solución

Entonces tu padre es $parid, y tu meta post tiene una clave de $metakey.

Vamos a pasarlo a una función para obtener sus hijos.

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

Luego ordenaremos el array $children, las claves serán los IDs de los posts y los valores serán los valores meta.

asort($children);

y definamos la función como:

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 {
        // ¡¡no hay hijos!!
        return array();
    }
}

Esto te da un array de IDs de posts y valores, ordenados de menor a mayor. Puedes usar otras funciones de ordenamiento de PHP para hacerlo de mayor a menor.

¿Y Qué Hay de los Hijos de los Hijos?

En medio de nuestro bucle, necesitamos hacer una llamada recursiva, pasando el ID del hijo en lugar del ID del padre.

Entonces esto:

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

Se convierte en esto:

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

// ahora obtenemos los hijos de los hijos
$grandchildren = get_children_with_meta( get_the_ID(), $metakey );

// fusionamos los nietos y los hijos en la misma lista
$children = array_merge( $children, $grandchildren );

Con esta modificación, la función ahora recupera los hijos, los hijos de los hijos, los hijos de los hijos de los hijos..... etc.

Al final puedes recortar los valores del array para obtener IDs así:

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

Usando esta estrategia, puedes reemplazar el valor de la clave meta con cualquier otra métrica, o usar funciones recursivas de otras maneras.

Dado que el código completo requiere solo unos segundos de comprensión básica y un rápido copiar y pegar, no insultaré tu inteligencia con un bloque de código completo para copiar y pegar.

Ventajas

  • Con modificación funciona para cualquier tipo de post y forma de datos
  • Puede modificarse para generar marcado anidado
  • Fácilmente cacheable para acelerar guardando los arrays retornados en transients
  • Se puede configurar con paginación aplicándola al WP_Query final

Problemas que Encontrarás

  • No tienes forma de saber cuántos hijos hay hasta que los hayas encontrado, por lo que los costos de rendimiento no escalan
  • Lo que quieres generará muchas consultas y es inherentemente costoso debido a las posibles profundidades involucradas.

Mi Recomendación

Recomendaría que aplanes tu jerarquía de páginas o uses una taxonomía en su lugar. Ej. si estás calificando posts, ten una taxonomía "Page Rating" con los términos 1,2,3,4 y 5 etc. Esto te proporcionará un listado de posts listo para usar.

Alternativamente, usa menús de navegación y evita este problema por completo

19 abr 2013 17:46:12
0

Obtener recursivamente todas las subpáginas actuales

Aquí tienes un enfoque recursivo usando get_children. Coloca lo siguiente en tu functions.php:

function get_all_subpages($page, $args = '', $output = OBJECT) {
    // Validar parámetro 'page'
    if (! is_numeric($page))
        $page = 0;

    // Configurar argumentos
    $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;

    // Validar parámetro 'output'
    $valid_output = array(OBJECT, ARRAY_A, ARRAY_N);
    if (! in_array($output, $valid_output))
        $output = OBJECT;

    // Obtener hijos
    $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];

        // Obtener subpáginas mediante recursión
        $subpages = array_merge($subpages, get_all_subpages($page, $args, $output));
    }

    return $subpages;
}

Cómo usarla

Usa la función anterior donde quieras, por ejemplo así:

$all_current_subpages = get_all_subpages(0);

La función soporta un parámetro args (cadena de consulta o array) y un tipo de output (ver arriba).

Así que también podrías usarla así:

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

Y debido a la dependencia get_children => get_posts => WP_Query puedes usar valores meta, como inicialmente solicitó el autor de esta pregunta.

14 abr 2013 04:22:48
0

He creado una función recursiva que obtiene todos los IDs de las páginas hijas de una página padre. Una vez que tenemos los IDs, hacemos una consulta para las páginas y podemos ordenar los resultados por clave/valor meta.

// Obtiene todos los IDs de los hijos de 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 ) // añade cada ID hijo al array
            $child_ids[] = $post->ID;

    if ( ! empty( $child_ids ) )
        foreach ( $child_ids as $child_id ) // añade más hijos al array
            $child_ids = array_merge( $child_ids, _get_children_ids( $child_id ) );

    return $child_ids;
}

$children_ids = _get_children_ids( 9 ); // usa tu ID de página numérico o get_the_id()

$results = new WP_Query( array(
    'post_type'   => 'page',
    'post__in'   => $children_ids
    #'meta_key'   => 'meta_key', // tu clave meta
    #'orderby'    => 'meta_key',
    /* 'meta_query' => array( // meta_query opcional
        array(
            'key' => 'meta_key', // clave
            'value' => array(3, 4), // valores
            'compare' => 'IN', // operador
        )
    ) */
) );

var_dump( $results );

Si necesitas ordenar los hijos por clave/valor meta de manera jerárquica, deberías pasar los valores meta_key y order_by al WP_Query en la función _get_children_ids (en lugar de al WP_Query final).

Si no, un método más simple para obtener todos los IDs hijos es:

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

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

No estoy seguro si esto es exactamente lo que buscas, pero podrías usar la función wp_list_pages y utilizar los parámetros 'child_of' y 'depth'.

Consulta la siguiente página en el Codex para más información: http://codex.wordpress.org/Function_Reference/wp_list_pages

30 nov 2011 16:58:57
1
-2

ESTO FUNCIONA, SOLO COPIA Y PEGA EL CÓDIGO EN TU ARCHIVO PAGE.PHP

//REDIRIGIR AL PRIMER HIJO DESDE LA PÁGINA PADRE

// Construir el array de argumentos para WP_Query()
$page_tree_query_args = array(
    'post_parent' => $post -> ID,
    'post_type' => 'page',
    'order' => 'asc'
);
// Obtener páginas hijas como objeto 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;
    wp_redirect( get_permalink( $first_subpage ) );
    exit;   
}
26 sept 2013 14:36:14
Comentarios

Esto A) no funciona ($post -> ID?), B) no es lo que se pidió, C) no está muy bien explicado.

tfrommen tfrommen
26 sept 2013 14:58:00