Получить все дочерние страницы родительской страницы с помощью WP Query

30 нояб. 2011 г., 12:57:46
Просмотры: 37.7K
Голосов: 15

Вот мой код

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

Он отображает только дочерние страницы первого уровня. Мне нужны все дочерние страницы, дочерние страницы дочерних страниц... и все остальные. Я искал решение и могу получить все дочерние страницы с помощью get_pages и wp_list_pages.

Но мне действительно нужно отсортировать порядок по значению произвольного мета-поля. Поэтому я должен использовать пользовательский запрос.

пожалуйста, помогите. Спасибо

2
Комментарии

Ниже вы говорите, что нашли ответ, какой именно?

Drew Baker Drew Baker
17 авг. 2012 г. 21:41:18

Вы проверяли функцию get_page_children?

t31os t31os
13 апр. 2013 г. 16:17:47
Все ответы на вопрос 6
5

Почему бы просто не использовать get_pages()?

Например:

<?php
// Определяем ID родительской страницы
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Получаем дочерние страницы в виде массива
$page_tree_array = get_pages( array(
    'child_of' => $parent_page_id;
) );
?>

Но если действительно необходимо получить объект WP_Query(), используйте аналогичный метод:

<?php
// Определяем ID родительской страницы
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Формируем массив аргументов для WP_Query()
$page_tree_query_args = array(
    'post_parent' => $parent_page_id;
);
// Получаем дочерние страницы в виде объекта WP_Query()
$page_tree_query = new WP_Query( $page_tree_query_args );
?>
30 нояб. 2011 г. 19:22:11
Комментарии

Если мы используем функцию get_pages(), мы не сможем реализовать сортировку (sort_column) для произвольных полей. Она принимает только поля таблицы post. Мне нужно реализовать сортировку для произвольного поля. Поэтому я использую wp_query(). Есть ли альтернативный способ?

phpuser phpuser
1 дек. 2011 г. 06:07:29

Вы видели вторую часть моего ответа, где я использую WP_Query()?

Chip Bennett Chip Bennett
1 дек. 2011 г. 15:59:53

Я попробовал этот код, но он возвращает только страницы первого уровня подчинения. Мне нужны подстраницы >> их подстраницы >> и т.д. (множественные уровни вложенности страниц). В итоге я нашел решение. Спасибо за ваш ответ.

phpuser phpuser
3 дек. 2011 г. 07:15:48

Какое у тебя решение!?

JCHASE11 JCHASE11
11 мар. 2013 г. 22:12:57

В определениях массивов выше есть точки с запятой, вызывающие синтаксические ошибки.

ptrin ptrin
22 янв. 2014 г. 05:49:11
0

Проблема

То, с чем у вас возникают сложности — "Как сделать X?" Это не одношаговое действие, а многоэтапный процесс, который нужно разбить на части.

Вам не нужно делать так:

получить все записи, которые являются дочерними для X, отсортированные по метаполю

Вам нужно сделать так:

получить все записи, которые являются дочерними для X
    для каждой дочерней записи получить все её дочерние записи
        для каждой дочерней записи получить все её дочерние записи
            ...
                упс, больше нет дочерних записей

Взять наш список записей и отсортировать их по метаполю

Общее решение

Чтобы понять, как делать это бесконечно, пока не достигнете конца, без жесткого кодирования, вам нужно понять рекурсивные функции.

Например:

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

Применение рекурсии к этой проблеме для решения

Итак, ваш родительский элемент — это $parid, а метаполе записи имеет ключ $metakey.

Давайте передадим его в функцию для получения дочерних элементов.

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

Затем мы отсортируем массив $children, где ключи — это ID записей, а значения — значения метаполей.

asort($children);

И определим функцию следующим образом:

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 {
        // нет дочерних элементов!!
        return array();
    }
}

Это дает вам массив ID записей и их значений, отсортированных от наименьшего к наибольшему. Вы можете использовать другие функции сортировки PHP для обратного порядка.

А что насчет дочерних элементов дочерних элементов?

В середине нашего цикла нам нужно сделать рекурсивный вызов, передавая ID дочернего элемента вместо родительского.

Так что это:

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

Превращается в это:

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

// теперь получаем дочерние элементы дочерних элементов
$grandchildren = get_children_with_meta( get_the_ID(), $metakey );

// объединяем дочерние и дочерние дочерних элементов в один список
$children = array_merge( $children, $grandchildren );

С этим изменением функция теперь получает дочерние элементы, дочерние элементы дочерних элементов, дочерние элементы дочерних элементов дочерних элементов..... и так далее.

В конце вы можете обрезать значения массива, чтобы получить ID таким образом:

$post_ids = array_keys( $children );
$q = new WP_Query( array( 'post__in' => $post_ids );
// и т.д.

Используя эту стратегию, вы можете заменить значение метаполя на любой другой критерий или использовать рекурсивные функции другими способами.

Поскольку полный код требует лишь нескольких секунд базового понимания и быстрого копирования-вставки, я не буду оскорблять ваш интеллект полным блоком кода для копирования.

Преимущества

  • С модификацией работает для любого типа записей и формы данных
  • Может быть модифицирован для генерации вложенной разметки
  • Легко кэшируется для ускорения, помещая возвращаемые массивы в транзиенты
  • Может быть настроен с постраничной навигацией, применяя её к конечному WP_Query

Проблемы, с которыми вы столкнетесь

  • У вас нет способа узнать, сколько дочерних элементов существует, пока вы их не найдете, поэтому производительность не масштабируется
  • То, что вы хотите, сгенерирует множество запросов и по своей природе затратно из-за потенциальной глубины вложенности.

Моя рекомендация

Я бы рекомендовал либо упростить вашу иерархию страниц, либо использовать таксономию вместо этого. Например, если вы оцениваете записи, создайте таксономию "Рейтинг страницы" с терминами 1, 2, 3, 4 и 5 и т.д. Это предоставит вам список записей "из коробки".

Альтернативно, используйте навигационные меню и полностью обойдите эту проблему.

19 апр. 2013 г. 17:46:12
0

Рекурсивное получение всех дочерних страниц

Рекурсивный подход с использованием get_children. Поместите следующий код в ваш файл functions.php:

function get_all_subpages($page, $args = '', $output = OBJECT) {
    // Проверка параметра 'page'
    if (! is_numeric($page))
        $page = 0;

    // Настройка аргументов
    $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;

    // Проверка параметра 'output'
    $valid_output = array(OBJECT, ARRAY_A, ARRAY_N);
    if (! in_array($output, $valid_output))
        $output = OBJECT;

    // Получение дочерних страниц
    $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];

        // Рекурсивное получение подстраниц
        $subpages = array_merge($subpages, get_all_subpages($page, $args, $output));
    }

    return $subpages;
}

Как использовать

Используйте эту функцию там, где вам нужно, например так:

$all_current_subpages = get_all_subpages(0);

Функция поддерживает параметр args (строка запроса или массив) и тип output (см. выше).

Также можно использовать следующим образом:

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

Благодаря зависимости get_children => get_posts => WP_Query вы можете использовать мета-значения, как изначально запрашивал автор вопроса.

14 апр. 2013 г. 04:22:48
0

Я создал рекурсивную функцию, которая получает все ID дочерних страниц родительской страницы. После получения ID мы делаем запрос для страниц и можем упорядочить результаты по мета-ключу/значению.

// Получает все ID дочерних страниц 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 ) // добавляем каждый ID дочерней страницы в массив
            $child_ids[] = $post->ID;

    if ( ! empty( $child_ids ) )
        foreach ( $child_ids as $child_id ) // добавляем дальнейших потомков в массив
            $child_ids = array_merge( $child_ids, _get_children_ids( $child_id ) );

    return $child_ids;
}

$children_ids = _get_children_ids( 9 ); // используйте ваш числовой ID страницы или get_the_id()

$results = new WP_Query( array(
    'post_type'   => 'page',
    'post__in'   => $children_ids
    #'meta_key'   => 'meta_key', // ваш мета-ключ
    #'orderby'    => 'meta_key',
    /* 'meta_query' => array( // опциональный meta_query
        array(
            'key' => 'meta_key', // ключ
            'value' => array(3, 4), // значения
            'compare' => 'IN', // оператор
        )
    ) */
) );

var_dump( $results );

Если вам нужно отсортировать дочерние страницы по мета-ключу/значению в иерархическом порядке, вы должны передать значения meta_key и order_by в WP_Query внутри функции _get_children_ids (вместо финального WP_Query).

Если это не требуется, более простой способ получить все ID дочерних страниц:

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

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

Не уверен, что это именно то, что вам нужно, но вы можете использовать функцию wp_list_pages с параметрами 'child_of' и 'depth'.

Подробнее об этом можно прочитать на странице Кодекса: http://codex.wordpress.org/Function_Reference/wp_list_pages

30 нояб. 2011 г. 16:58:57
1
-2

ЭТО РАБОТАЕТ, ПРОСТО СКОПИРУЙТЕ И ВСТАВЬТЕ КОД В ВАШ ФАЙЛ PAGE.PHP

//ПЕРЕНАПРАВЛЕНИЕ НА ПЕРВУЮ ДОЧЕРНЮЮ СТРАНИЦУ ИЗ РОДИТЕЛЬСКОЙ

// Формируем аргументы для WP_Query()
$page_tree_query_args = array(
    'post_parent' => $post -> ID,
    'post_type' => 'page',
    'order' => 'asc'
);
// Получаем дочерние страницы в виде объекта 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 сент. 2013 г. 14:36:14
Комментарии

Это: A) не работает ($post -> ID?), B) не то, что просили, C) объяснено не очень хорошо.

tfrommen tfrommen
26 сент. 2013 г. 14:58:00