Во-первых, вам нужно определить отношение внутри вашего комментария класса модели:
public function getChildComments()
{
return $this->hasMany(self::className(), ['parent_id' => 'id']);
}
Это определяет отношение сущности к себе. Я думаю, что всегда полезно также хранить связанную логику или обработчики в вспомогательных / вызываемых методах в одном классе таким образом, чтобы не требовалось загружать их все сразу из базы данных. Что будет дальше, должен ответить на вопрос:
Как мне показать вложение?
CASE01: Внутри приложения RESTFul
Просто переопределить fields()
внутри Комментарий класс, чтобы всегда выводить дочерние комментарии:
public function fields()
{
$fields = parent::fields();
$fields['childs'] = 'childComments';
return $fields;
}
Вот и все. yii \ rest \ Serializer должен позаботиться о рекурсивном представлении, и вы получите нечто похожее на это при выводе списка комментариев:
CASE02: внутри веб-представления HTML
Вероятно, есть много способов достичь этого. Самым простым и чистым способом, который я мог придумать, является привязка к движку шаблонов, который Yii уже использует для рекурсивного представления представления, содержащего дочерние комментарии. В качестве рабочего примера добавьте что-то вроде следующего в ваш файл index.php :
<?php
use yii\helpers\Html;
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
use app\models\Comment;
?>
<?= ListView::widget([
'dataProvider' => new ActiveDataProvider([
'query' => Comment::find(),
]),
'itemView' => '_comment',
'itemOptions' => ['style' => 'padding: 10px 50px; border: 1px solid red'],
]); ?>
Затем создайте этот _comment.php файл:
<?php
use yii\helpers\Html;
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
?>
<div style="background-color: skyblue; padding: 5px 15px">
<h4><?= Html::encode($model->id) ?></h4>
<p><?= Html::encode($model->name) ?></p>
</div>
<?php
if ($model->getChildComments()->count()) {
echo ListView::widget([
'dataProvider' => new ActiveDataProvider([
'query' => $model->getChildComments(),
]),
'itemView' => '_comment',
'itemOptions' => ['style' => 'padding: 10px 0 10px 50px; border: 1px dotted blue'],
]);
}
?>
Шаблон будет создавать свой новый экземпляр каждый раз, когда обнаружит, что childComments
связан с представленным. С этим битом CSS-отступов, чтобы показать вложенность, этот код должен вывести это: