Древовидные комментарии.

Написана 7 Февраля, 2012 в 19:47. Автор: borN_free   |   Теги: комментарии, tree, comments Комментарии 12

Древовидные комментарииТема древовидных комментариев заезжена до ужаса, но, тем не менее, хотелось бы о ней поговорить и здесь. Я не буду затрагивать сторону Nested Sets, а покажу простую реализацию с помощью foreign key и рекурсии.

Покажу на примере того, как реализованы комментарии в моем блоге (упрощенный вариант). Для начала давайте создадим таблицу:

CREATE TABLE 'comment' (
 'id' int(11) NOT NULL AUTO_INCREMENT,
 'parent_id' int(11) DEFAULT NULL,
 'content' text COLLATE utf8_unicode_ci NOT NULL,  
 'author' varchar(128) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY ('id'),
 KEY 'FK_parent_id` ('parent_id'),
 CONSTRAINT 'FK_parent_post' FOREIGN KEY ('parent_id') 
REFERENCES 'comment' ('id') ON DELETE CASCADE 
ON UPDATE CASCADE
) ENGINE=InnoDB;

Для простоты я убрал все лишние поля. Итак, самое главное - это хранить у каждого комментария его родителя. Условимся, что комментарии самового верхнего уровня имеют в качестве родителя NULL.

"Я хочу, чтобы при удалении комментария удалялись его дочерние" - скажете вы. Без проблем. Магия заключается в том, что мы добавляем внешний ключ (parent_id), который будет ссылаться на поле id. Теперь, если мы удалим комметарий, то каскадно удалятся все зависимые, без всяких написаний хранимых процедур или рекурсивного удаления через PHP. Все будет происходить на уровне СУРБД (MySQL например).

А сейчас нам надо вывести их на страницу. Здесь в любом случае понадобиться рекурсия. Приступим. Я покажу как выводятся комметарии здесь, на сайте. Смысл заключается в том, что выбираются все записи, рекурсивно складываются в не иерархический массив (этим мы избегаем использования рекурсивной функции при генерации HTML), и выводятся с отступами согласно "вложенности". Можете посмотреть исходный код страницы - там нет никаких вложенных div или ul-li, если конечно комментарии существуют к данному посту =). Приведу сразу ViewHelper с пояснениями:

class PostViewHelper {
    const NO_PARENT_ID = 0;
    private static $level = -1;

    public static function getCommentsTree($comments) {
        $cats = array();

        // проходим по ВСЕМ комментариям и формируем массив
        foreach ($comments as $comment) {
            // ключ массива - родитель текущего комментария
            $cats[(int) $comment->parent_id][] = array(
                'comment_id' => $comment->id,
                'content' => $comment->content,                
                'authorLink' => $comment->authorLink,
            );
        }
        // теперь просто вызываем рекурсивную функцию
        return self::buildTreelikeArray($cats, self::NO_PARENT_ID);
    }

    public static function buildTreelikeArray($cats, $parent_id) {
        // каждый раз увеличиваем статическую переменную уровня
        self::$level++;
        $result = array();

        if (is_array($cats) && isset($cats[$parent_id])) {
            foreach ($cats[$parent_id] as $cat) {
                $cat['level'] = self::$level;
                $result[] = $cat;
                $result = array_merge($result, self::buildTreelikeArray($cats, $cat['comment_id']));
                self::$level--;
                // для создания иерархического массива
                //$result[] = self::buildTreelikeArray($cats, $cat['comment_id']);
            }
        } else {
            return array();
        }
        return $result;
    }
}

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

12 comments

+3 ответить
April 9, 2013 at 07:09 am

проверка работы формы

+5 ответить
June 6, 2015 at 08:24 pm

Answer test

-3 ответить
fegfejk:
September 27, 2015 at 04:53 pm

htjuhtujt76u

-3 ответить
April 8, 2016 at 04:10 pm

c

+5 ответить
April 30, 2016 at 03:21 pm

джьвма

ответить
gdfg:
May 21, 2016 at 10:53 pm

gdfgdf

+2 ответить
April 15, 2016 at 05:21 pm

хорошая идея. может подскажите как этим классом пользоваться. я передаю выборку из БД в getCommentsTree() выходит не то и замичание что Trying to get property of non-object в строках 'comment_id' => $comment->id и тд

ответить
July 22, 2017 at 12:00 am

Круто!

ответить
July 22, 2017 at 12:03 am

Test

ответить
July 22, 2017 at 12:03 am

Test 2

ответить
August 17, 2017 at 03:21 am

In 1957, the Earl launched an ultra thin watch to subvert the omega replica watches watchmaking world, and reinterpreted the definition of elegant watches. In this year, to celebrate the birth of the fake rolex watches replica 60th anniversary tab paragon, the grand launch of its present slim elegant concept Altiplano limited edition watch iwc watches series, the reappearance of extraordinary masterpiece.

ответить
September 21, 2017 at 01:51 am

There’s just something special about having a rolex replica sale on your wrist. And when it comes rolex replica sale in pink-ish or rose gold tones, fashion brands have really outdone themselves in the way of marketing low-end forgettable pieces to women. La société suédoise a en effet associé ingénierie de pointe, design scandinave dernier cri et tradition horlogère suisse pour donner naissance à cette nouvelle génération de replique montres hybride.Freedom, comfort, functionality—these were the three requirements at the top of Gabrielle "Coco" fake chanel handbags ’ list when she created a handbag that merged practicality with style in 1955. Her idea of dressing the modern woman still rings true today, and it’s nowhere more apparent than in the new bag that bears her name.One of the drawbacks, however, is the risk of losing the personal touch associated with crafting replica handbags since everything is created on a computer and more robotic or uniform.“The factories are the reason I decided to join cheap mulberry bags,” he says. “I would never change that, it is so good to work so closely with the people who make the bags.

Оставьте свой комментарий:

Поля с * обязательны.