【问题标题】:Nesting Comments Yii2嵌套评论 Yii2
【发布时间】:2018-06-30 19:08:21
【问题描述】:

我有一个评论表,如下所示:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| user_id   | int(11)      | NO   |     | NULL    |                |
| parent_id | int(11)      | NO   |     | 0       |                |
| post_id   | int(11)      | NO   |     | NULL    |                |
| body      | text         | NO   |     | NULL    |                |
| date      | datetime     | NO   |     | NULL    |                |
| status    | tinyint(1)   | NO   |     | 0       |                |
+-----------+--------------+------+-----+---------+----------------+

评论parent_id默认为0,如果评论被回答,则在parent_id列中插入父id。

并使用以下代码与用户表建立关系:

public function getPosts()
{
    return $this->hasMany(Post::className(), ['category_id' => 'id']);
}

如何显示嵌套?

【问题讨论】:

  • 层次结构的最大级别是多少,或者假设您正在使用邻接列表模型,需要多少自连接才能检索任何顶级评论的单个路径?跨度>
  • 没有限制,awirete a comment,b replay to a,c replay to b and ...,我需要一个递归函数来显示所有评论。

标签: activerecord yii2


【解决方案1】:

首先,您需要在 Comment 模型类中定义关系:

public function getChildComments()
{
    return $this->hasMany(self::className(), ['parent_id' => 'id']);
}

这定义了实体与自身的关系。我认为将相关逻辑或处理程序保留在同一个类中的帮助器/可调用方法中总是好的,这种方法不需要从数据库中一次加载它们。接下来应该回答这个问题:

如何显示嵌套?


CASE01:在 RESTFul 应用程序中

只需在 Comment 类中覆盖 fields() 以始终输出子 cmets:

public function fields()
{
    $fields = parent::fields();
    $fields['childs'] = 'childComments';
    return $fields;
}

就是这样。 yii\rest\Serializer 应该处理递归表示,并且在输出 cmets 列表时会得到类似的结果:


CASE02:在 HTML Web 视图中

可能有很多方法可以实现它。我能想到的最简单和最干净的方法是绑定 Yii 已经使用的模板引擎,以递归方式重新渲染包含子 cmets 的视图。作为一个工作示例,将以下内容添加到您的 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 填充来显示嵌套,该代码应该输出以下内容:

【讨论】:

  • 我不明白,我写了一个像getChildComments()这样的函数来获取childeren,它在一级有效,在递归函数中不起作用,我如何在递归函数中使用它?
  • @Masoud92m 现在呢?
  • 谢谢。很高兴它有帮助
猜你喜欢
  • 2021-09-09
  • 2012-09-17
  • 2014-08-28
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 2021-03-04
相关资源
最近更新 更多