Статьи из рубрики comment
Модерация и вывод комментариев
Ответ на комментарии и рекурсивный вывод
На сайте оставили комментарий, вы ответили. Оппонент что-то еще уточнил, вы опять ответили. Цепочка из нескольких вопросов/ответов, которую нужно представить в виде лестницы.
Отступы можно выводить в обычном цикле, но если отступы формируются с помощью блочных элементов и css
, то проще использовать рекурсию.
Поиск
Метки
Модерация и вывод комментариев
Ответ на комментарии и рекурсивный вывод
На сайте оставили комментарий, вы ответили. Оппонент что-то еще уточнил, вы опять ответили. Цепочка из нескольких вопросов/ответов, которую нужно представить в виде лестницы.
Отступы можно выводить в обычном цикле, но если отступы формируются с помощью блочных элементов и css
, то проще использовать рекурсию.
Представьте минидиалог.
- Подскажите, как организовать комментарии на сайте?
- Есть варианты. Каковы ваши требования?
- Необходимо, чтобы юзер мог оставить комментарий, который будет размещен после модерации.
- Добрый день! У меня такая же проблема.
- Можно использовать следующий алгоритм ... [Ответить]
В каждом мини-диалоге участвуют двое. Если кто-то еще оставляет комментарий, то это новый мини-диалог. Вклиниться в мини-диалог стороннему комментатору нельзя.
Нужно, чтобы человек мог оставить отзыв, который можно было бы разместить, после модерации. Допустим, что комментарии могут оставлять только авторизованные пользователи и только во frontend
.
Вы администратор сайта и вы видите оставленный комментарий в backend
. Вы отвечаете на комментарий.
У пользователя, оставившего комментарий, должен отобразиться ваш ответ во frontend
и кнопка [Ответить].
При упомянутом ограничении, а именно - в диалоге участвуют только двое: администратор и комментатор, структура данных для хранения комментариев примерно следующая.
id integer post_id integer user_id integer content text status integer last boolean thread char(32) created_at integer
Нить диалога
Каждый новый комментарий получает уникальное значение - код нити (thread
). Ответный комментарий получает то же значение thread
, что и начальный комментарий. Если отсортировать все комментарии с одинаковым значением thread
по дате, то получим цепочку диалога.
content | thread |
---|---|
Подскажите, как организовать комментарии на сайте? | a1 |
Есть варианты. Каковы ваши требования? | a1 |
Необходимо, чтобы юзер мог оставить комментарий, который будет размещен после модерации. | a1 |
Добрый день! У меня такая же проблема. | b2 |
Можно использовать следующий алгоритм ... | b2 |
Вывод комментариев в backend
Вывод комментариев уступами можно выполнить с помощью стандартного Grid
, если сохранить текущее значение thread
и использовать его при выводе следующего комментария. Для сохранения используем внутреннюю переменную params
класса yii\base\View.
<?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'layout' => "{items}\n{summary}\n{pager}", 'columns' => [ ... [ 'attribute' => 'content', 'value' => function($data) { // declare params for indention in a row, // using View class internal variable - params if(!isset($this->params['thread'])) $this->params['thread'] = false; if($this->params['thread'] == $data->thread) $this->params['indention'] .= '--'; else { $this->params['thread'] = $data->thread; $this->params['indention'] = ''; } return $this->params['indention'] . ' ' . $data->content; } ], ...
Вывод комментариев во frontend
Верстка во frontend
, как правило, более изощренная и часто основана на bootstrap media object. Начинается вывод с frontend/views/post/view.php
в котором где-то, после текста поста, присутствует следующий код:
<?php echo $this->render('_comments', [ 'post' => $model, 'comments' => $model->comments, ]); ?>
Комментарии выводятся один за другим. Если у комментариев одинаковый thread
, то нужно сделать отступ и напечатать текущий комментарий. И так далее, пока не изменится thread
. Рекурсивно подобный процесс представить легче.
Рекурсия
Определим основной цикл вывода frontend/views/post/_comments.php
. Как и в backend
промежуточные переменные сохраняются во внутренней переменной params
класса yii\base\View.
<?php function close_thread($level) { while($level > 1) { $level--; echo '</div>'; } } ?> <?php $i = 0; $this->params['comments'] = $comments; ?> <ul class="media-list"> <?php while($i < count($comments)): ?> <li class="media"> <?php echo $this->render('_comment', [ 'i' => $i, 'thread' => $comments[$i]->thread, 'level' => 0]); $i = $this->params['comment_i']; ?> </li> <!-- .media / --> <?php endwhile; ?> </ul>
При выводе текущего комментария frontend/views/post/_comment.php
новый блок (отступ) выводится пока thread
тот же, что и у предыдущего комментария. Если же thread
изменился, то блоки закрываются.
<?php $comment = $this->params['comments'][$i]; ?> <div class="media-left"> <i class="fa fa-2x fa-user"></i> </div> <div class="media-body"> <div class="media-content"> <h4 class="media-heading"><?= $comment->author->name ?></h4> <div class="alert alert-info" role="alert"><?= $comment->content ?></div> <?php if($comment->canBeAnswered()): ?> <div class="text-right"> <a href="#comment-area" data-comment-thread="<?= $comment->thread ?>" class="btn btn-info reply-btn"> <?= \Yii::t('app', 'Reply') ?> </a> </div> <?php endif; ?> </div> <?php $i++; $this->params['comment_i'] = $i; if($i < count($this->params['comments'])) { $comment = $this->params['comments'][$i]; if($thread == $comment->thread) { $level++; echo '<div class="media-body">'; echo $this->render('_comment', ['i' => $i, 'thread' => $thread, 'level' => $level]); } else close_thread($level); } else { close_thread($level); } ?>
Право на ответ
Метод canBeAnswered()
модели Comment
вызывается во frontend
при определении права текущего пользователя отвечать на последний комментарий.
Пользователь имеет право ответить на комментарий, если:
- Пользователь авторизован;
- Пользователь является инициатором мини-диалога;
- Это последний комментарий в мини-диалоге;
- И последний комментарий принадлежит модератору.
public function canBeAnswered() { $countInThread = Comment::find() ->where(['thread' => $this->thread, 'user_id' => \Yii::$app->user->id]) ->count(); return !\Yii::$app->user->isGuest && $this->last && // this is a last comment in a thread \Yii::$app->user->identity->group == User::GROUP_COMMENTATOR && // you are a commentator $this->user_id != \Yii::$app->user->id && // last comment not yours $countInThread > 0; // you begin this thread }
Как это работает во frontend
, можно посмотреть на сайте. О backend
подробнее в расширении sergmoro1/yii2-blog-tools.
Заключение
Комментарии в расширении sergmoro1/yii2-blog-tools могут оставлять только зарегистрированные пользователи. Комментарии должны модерироваться администратором сайта. Диалог возможен только между пользователем и администратором сайта.
Оставить комментарий
Только авторизованные пользователи могут оставлять комментарии. Пожалуйста авторизуйтесь или пройдите регистрацию.
Можно авторизоваться, используя социальную сеть-
-
-
-