Как создать блогролл с постами, отсортированными по категориям и подкатегориям?

15 мая 2013 г., 02:41:37
Просмотры: 13.6K
Голосов: 0

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

Желаемый HTML-результат, который я хочу видеть, должен выглядеть примерно так:

<div id="content">
    <div id="category1">
        <ul id="posts">
            <li>post1</li>
            <li>post2</li>
            <li>post3</li>
        </ul><!-- #posts -->
    </div><!-- #category1 -->

    <div id="category2">
        <div id="sub-category1">
            <ul id="posts">
                <li>post4</li>
                <li>post5</li>
                <li>post6</li>
            </ul><!-- #posts -->
        </div><!-- #sub-category1 -->

        <div id="sub-category2">
            <ul id="posts">
                <li>post7</li>
                <li>post8</li>
                <li>post9</li>
            </ul><!-- #posts -->
        </div><!-- #sub-category2 -->
    </div><!-- #category2 -->
</div><!-- #content -->

Структура файлов, которую я предполагаю использовать, будет выглядеть примерно так:

custom-category.php // этот файл будет извлекать категории, сортировать их и создавать контейнеры div для #category и #sub-category, вызывая информацию о постах из своего цикла/запроса с помощью get_template_part( 'content', get_post_format() );

content.php // этот файл будет сортировать ul#posts и всю информацию, которую я могу добавить относительно самого поста

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

Я пробовал искать плагины, но некоторые только сортируют категории в боковых панелях, другие позволяют создавать пользовательские поля для категорий, но в отзывах упоминается, что нельзя вызывать эти значения. Я пробовал функцию wp_list_categories(); чтобы попытаться начать с чего-то, но она даже не выводит подкатегории.

Я читал о создании собственных query_posts(); или get_posts();, но я действительно не знаю, с чего начать с ними.

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

1- Как начать "Цикл" для получения категорий/подкатегорий?
2- Как отсортировать категории и сохранить вложенность подкатегорий?
3- Как я могу убедиться, что посты попадут в нужные div'ы? На всякий случай, если WP сделает что-то странное.

Спасибо за помощь.

--- Обновление ---

Я искал решения в интернете и начинаю продвигаться вперед, но пока не совсем там. Вот что у меня есть на данный момент:

<?php
        // получаем все категории из базы данных
        $args1 = array(
          'orderby' => 'ID',
          'order' => 'ASC',
          'hierarchical' => true,
          );
        $cats = get_categories( $args1 ); 

            // перебираем категории
            foreach ($cats as $cat) {
                // получаем ID категории
                $cat_id= $cat->term_id;
                // Создаем заголовок для категории
                echo "<h2>".$cat->name."</h2><p>".$cat->term_id."</p>";
                // создаем пользовательский запрос WordPress
                $args2 = 'cat=' . $cat_id . '&orderby=date&order=DESC&post_per_page=-1';
                query_posts( $args2 );
                // запускаем цикл WordPress!
                if (have_posts()) : while (have_posts()) : the_post(); ?>

                    <?php // создаем нашу ссылку теперь, когда пост настроен ?>
                    <a href="<?php the_permalink();?>"><?php the_title(); ?></a>
                    <?php echo '<hr/>'; ?>

                <?php endwhile; endif; // завершаем наш цикл WordPress. Он начнется снова для каждой категории ?>
            <?php } // завершаем оператор foreach ?>

Я нашел этот фрагмент кода на этом сайте. Он выводит все категории и размещает посты под ними, но дублирует посты для родительской категории следующим образом:

<h2>Category1</h2><p>2</p> 
    <a href="http://localhost/wordpress/2013/05/06/test0/">test0</a>
                    <hr> 
<h2>Category2</h2><p>3</p>
    <a href="http://localhost/wordpress/2013/05/15/test2/">test2</a>
                    <hr> 
    <a href="http://localhost/wordpress/2013/05/14/test1/">test1</a>
                    <hr> 
<h2>Sub-category1</h2><p>4</p>
    <a href="http://localhost/wordpress/2013/05/14/test1/">test1</a>
                    <hr> 
<h2>Sub-category2</h2><p>5</p>
    <a href="http://localhost/wordpress/2013/05/15/test2/">test2</a>
                    <hr> 

Как видите, посты test1 и test2 отображаются в Category2, а это не совсем то, что я хотел, как описано в первоначальном вопросе (конечный HTML-результат).

Я считаю, что мне нужно добавить условный оператор для проверки, есть ли у текущей категории дочерние элементы, и если они есть, перейти к дочерним категориям, если нет - заполнить ее. Но я все еще пытаюсь понять, как это сделать. Я еще не достиг точки, где я чувствую себя достаточно комфортно, чтобы начать пытаться реализовать div'ы, которые я планирую иметь в конечном HTML-результате, но у меня есть ощущение, что у меня также возникнут проблемы с этим. На данный момент я в основном пытаюсь узнать больше об этом "цикле", пока не получу достойный результат, который позволит мне разобраться во всем этом.

Я знаю об этих 2 ссылках A и B, но я все еще новичок и пока не могу добраться туда, поэтому я в основном работаю с кодом, который, как я вижу, работает, и буду пытаться улучшить его по мере продвижения.

--- Обновление ---

Кажется, это выводит посты в правильном порядке и без повторения для родительских категорий.

<?php
        // получаем все категории из базы данных
        $args1 = array(
          'orderby' => 'ID',
          'order' => 'ASC',
          'hierarchical' => true
          );
        $cats = get_categories( $args1 ); 

            // перебираем категории
            foreach ($cats as $cat) {
                $cat_id= $cat->term_id;// получаем ID категории
                $cat_name= $cat->name;// получаем название категории
                $parent= $cat->category_parent;// получаем родительскую категорию
                $cat_child= get_term_children( $cat_id, 'category' ); // функция, которую я использовал get_category_children(); была устаревшей... исправил это

                $has_child=bool; //
                if( empty($cat_child)) { $has_child= false; }
                else { $has_child= true; }

                if ( $parent == 0 && $has_child == true ) { // является родительской И имеет дочерние -> заголовок поста
                    echo "<h2>".$cat_name."</h2>";
                    echo '<hr/>'; }
                elseif ( $parent == 0 && $has_child == false ) { // является родительской И не имеет дочерних -> цикл постов
                    echo "<h2>".$cat_name."</h2>";
                    // создаем пользовательский запрос WordPress
                    $args2 = 'cat=' . $cat_id . '&orderby=date&order=DESC&post_per_page=-1';
                    query_posts( $args2 );
                    // запускаем цикл WordPress!
                    if (have_posts()) : while (have_posts()) : the_post(); ?>
                        <?php the_title(); ?>
                        <?php echo '<hr/>'; ?>
                    <?php endwhile; endif; }
                else { // является дочерней -> цикл постов
                    echo "<h2>".$cat_name."</h2>";
                    // создаем пользовательский запрос WordPress
                    $args2 = 'cat=' . $cat_id . '&orderby=date&order=DESC&post_per_page=-1';
                    query_posts( $args2 );
                    // запускаем цикл WordPress!
                    if (have_posts()) : while (have_posts()) : the_post(); ?>
                        <?php the_title(); ?>
                        <?php echo '<hr/>'; ?>
                    <?php endwhile; endif;   // завершаем наш цикл WordPress. Он начнется снова для каждой категории ?>
            <?php }} // завершаем оператор foreach ?>

Я разделил это на 3 условия: является родительской и имеет дочерние, является родительской, но не имеет дочерних и является дочерней. Функция, которая позволила мне добраться сюда, - это get_term_children();.

Читая код сейчас, я понимаю, что мог просто проверить, пуст ли $cat_child непосредственно в основных операторах if/elseif, избегая обхода $has_child.

0
Все ответы на вопрос 1
0

Хорошо, после долгих поисков я пришел к коду, который делает именно то, что я хотел. Однако, я не считаю этот код красивым/эффективным/переиспользуемым. Я просто публикую его, поскольку он выполняет ожидаемое. Я был бы признателен за ответ, который укажет мне на "лучшие практики" программирования, чтобы я мог поучиться, поэтому не буду отмечать вопрос как отвеченный примерно неделю, чтобы дождаться более качественного кода.

Вот результат, к которому я пришел:

<?php
        $isOdd = true; // флаг для определения id родительского div для CSS
        $args1 = array(
          'orderby' => 'ID',
          'order' => 'ASC',
          'hierarchical' => true
          );
        $cats = get_categories( $args1 ); // получаем все категории из базы данных

            // перебираем категории
            foreach ($cats as $cat) {
                $cat_id= $cat->term_id; // ID категории
                $cat_name= $cat->name; // название категории
                $parent= $cat->category_parent; // родительская категория
                $cat_child= get_term_children( $cat_id, 'category' ); // получаем дочерние категории из таксономии

                $has_child=bool; // переменная для проверки наличия дочерних категорий
                if( empty($cat_child)) { $has_child= false; }
                else { $has_child= true; }

                if ( $parent == 0 && $has_child == false ) { // если родительская и без дочерних - выводим записи
                    echo "<div class=\"parent-wrap\" id=\"". ( $isOdd ? 'odd' : 'even') . "\">";
                        echo "<h2>".$cat_name."</h2>";
                        echo "<div class=\"post-wrap\">";
                            echo "<ul class=\"post-list\">";
                                echo "<li class=\"back-button\"><</li>";

                                    // создаем кастомный запрос WordPress
                                    $args2 = 'cat=' . $cat_id . '&orderby=date&order=DESC&post_per_page=-1';
                                    query_posts( $args2 );
                                    // запускаем цикл WordPress
                                    if (have_posts()) : while (have_posts()) : the_post(); 
                                        get_template_part( 'content', get_post_format() ); // получаем шаблон поста из content.php
                                    endwhile; endif;

                                echo "<li class=\"front-button\">></li>";
                            echo "</ul><!-- .post-list -->";
                        echo "</div><!-- .post-wrap -->";
                    echo "</div><!-- .parent-wrap -->";
                    $isOdd = !$isOdd;
                    }
                elseif ( $parent == 0 && $has_child == true ) { // если родительская и есть дочерние - выводим заголовок
                    echo "<div class=\"parent-wrap\" id=\"". ( $isOdd ? 'odd' : 'even') . "\">";
                        echo "<h2>".$cat_name."</h2>";

                        // перебираем категории внутри условия elseif
                        foreach ($cats as $cat) {
                            $cat_id_new= $cat->term_id; // новый ID категории
                            $cat_name_new= $cat->name; // новое название категории
                            $parent_new= $cat->category_parent; // новый родитель категории
                            $cat_child_new= get_term_children( $cat_id_new, 'category' ); // получаем новые дочерние категории

                            $has_child_new=bool; // новая переменная для проверки дочерних категорий
                            if( empty($cat_child_new)) { $has_child_new= false; }
                            else { $has_child_new= true; }

                            if ($parent_new != 0 && $has_child_new == false && cat_is_ancestor_of($cat_id, $cat_id_new) ) { // если дочерняя - выводим записи
                                echo "<div class=\"child-wrap\">";
                                    echo "<h3>".$cat_name_new."</h3>";
                                    echo "<div class=\"post-wrap\">";
                                        echo "<ul class=\"post-list\">";
                                            echo "<li class=\"back-button\"><</li>";

                                                // создаем кастомный запрос WordPress
                                                $args2 = 'cat=' . $cat_id_new . '&orderby=date&order=DESC&post_per_page=-1';
                                                query_posts( $args2 );
                                                // запускаем цикл WordPress
                                                if (have_posts()) : while (have_posts()) : the_post(); 
                                                    get_template_part( 'content', get_post_format() ); // получаем шаблон поста из content.php
                                                endwhile;
                                                endif; // завершаем цикл WordPress. Он запустится снова для каждой категории 

                                            echo "<li class=\"front-button\">></li>";
                                        echo "</ul><!-- .post-list -->";
                                    echo "</div><!-- .post-wrap -->";
                                echo "</div><!-- .child-wrap -->";
                            } // закрываем if ($parent_new != 0...
                        } // закрываем foreach в elseif
                    echo "</div><!-- .parent-wrap -->";
                    $isOdd = !$isOdd;
                } // закрываем if ($parent == 0...
            } // закрываем первый foreach ?>

Мне кажется, что некоторые вещи в этом коде можно было бы лучше организовать, создав функции и затем переиспользуя их по всему коду, и я все еще думаю о замене query_posts(); на get_posts(); или pre_get_posts();.

17 мая 2013 г. 18:22:37