多层评论系统Laravel

O P*_*O P 23 php recursion laravel laravel-5

我对刀片递归部分视图有困难.除了comment.blade.php文件中的递归之外,一切都适用于大多数情况.

我知道我需要使用一个foreach @include('articles.comments.comment', $comment)再次召唤自己,但我不知道如何调用它.

article_comments表:

id
message
user_id
parent_id
created_at
updated_at
Run Code Online (Sandbox Code Playgroud)

app\Article.php类:

class Article extends Model {

    protected $table = 'articles';

    protected $fillable = [
        'category',
        'title',
        'permalink',
        'synopsis',
        'body',
        'source',
        'show_author',
        'published_at'
    ];

    protected $dates = ['published_at'];

    public function scopePublished($query)
    {
        $query->where('published_at', '<=', Carbon::now());
    }

    public function setPublishedAtAttribute($date)
    {
        $this->attributes['published_at'] = Carbon::parse($date);
    }

    public function comments()
    {
        return $this->hasMany('App\Comments')->where('parent_id', 0);
    }

}
Run Code Online (Sandbox Code Playgroud)

app\Comments.php类:

class Comments extends Model {

    protected $table = 'article_comments';

    protected $fillable = [
        'parent_id',
        'message',
    ];

    public function author() {
        return $this->belongsTo('App\User'); 
    }

    public function children()
    {
        return $this->hasMany('App\Comments', 'parent_id');
    }

    public function countChildren($node = null)
    {
        $query = $this->children();
        if (!empty($node)) {
            $query = $query->where('node', $node);
        }

        $count = 0;
        foreach ($query->get() as $child) {
            // Plus 1 to count the direct child
            $count += $child->countChildren() + 1; 
        }
        return $count;
    }

}
Run Code Online (Sandbox Code Playgroud)

app\Http\Controllers\ArticlesController.php:

public function show($permalink)
{
    $article = Article::where('permalink', '=', $permalink)->with('comments','comments.author','comments.children')->first();
    if ($article != null) {
        $comments = $article->comments;
        return view('articles.show', compact('article','comments'));
    } else {
        return redirect('/')->with('error', 'This article does not exist.');
    }
}
Run Code Online (Sandbox Code Playgroud)

资源\意见\文章\ show.blade.php

@if (count($comments) > 0)
    <ul>
    @foreach ($comments as $comment)
        @include('articles.comments.comment', ['comment'=>$comment])
    @endforeach
    </ul>
@else
    no comments
@endif
Run Code Online (Sandbox Code Playgroud)

资源\意见\文章\评论\ comment.blade.php

<li>
    {{ $comment->message }}

    @if (count($comment->children) > 0)
        <ul>
        @foreach ($comment->children as $child)
            @include('articles.comments.comment', ['comment'=>$child])
        @endforeach
        </ul>
    @endif
</li>
Run Code Online (Sandbox Code Playgroud)

当前错误:

Invalid argument supplied for foreach() (View: /var/www/dev.example.com/resources/views/articles/comments/comment.blade.php) (View: 
Run Code Online (Sandbox Code Playgroud)

Jef*_*eff 10

你很亲密.我认为这应该有效:

资源\意见\文章\ show.blade.php

@if (count($comments) > 0)
    <ul>
        @each('articles.comments.comment', $comments, 'comment');
    </ul>
@else
    no comments
@endif
Run Code Online (Sandbox Code Playgroud)

资源\意见\文章\评论\ comment.blade.php

<li>
    {{ $comment->message }}

    @if (count($comment->children) > 0)
        <ul>
            @each('articles.comments.comment', $comment->children, 'comment');
        </ul>
    @endif
</li>
Run Code Online (Sandbox Code Playgroud)

应用程序\ HTTP \控制器\ ArticlesController.php:

$article = Article::where('permalink', '=', $permalink)->with('comments','comments.author','comments.children')->first();
$comments = $article->comments;
return view('articles.show', compact('article','comments'));
Run Code Online (Sandbox Code Playgroud)

  • 修复了`@include`语句来正确传递变量.请参阅:https://laravel.com/docs/5.1/blade#control-structures (2认同)

Blu*_*nie 6

首先,我看到您将所有注释放在一个页面中而没有任何分页,但是,您comments()Article模型上的方法限制为只parent_id=0需要获取根注释的注释.但是,在你的代码进一步看,在你的控制器,你懒加载comments.authorcomments.children沿.请注意,延迟加载仅发生在第一个父注释中,之后,所有子项都必须通过急切加载关系来进行大量查询才能获得关系.

如果您希望将所有注释放在一个页面中,我建议您删除parent_id=0约束并一次加载注释并应用策略来对它们进行排序.这是一个例子:

应用程序\ Article.php

class Article extends Model {

    // ...

    public function comments()
    {
        return $this->hasMany('App\Comments');
    }

}
Run Code Online (Sandbox Code Playgroud)

应用程序\ HTTP \控制器\ ArticlesController.php

use Illuminate\Database\Eloquent\Collection; 

// ...

public function show($permalink)
{
    $article = Article::where('permalink', '=', $permalink)->with('comments','comments.author','comments.children')->first();

    if ($article != null) {

        $comments = $this->buildCommentTree($article->comments);

        return view('articles.show', compact('article','comments'));
    } else {
        return redirect('/')->with('error', 'This article does not exist.');
    }
}


protected function buildCommentTree(Collection $comments, $root = 0)
{
    $branch = new Collection();

    $comments->each(function(Comment $comment) use ($root) {
        if ($comment->parent_id == $root) {

            $children = $this->buildCommentTree($comments, $comment->getKey());

            $branch->push($comment);
        } else {
            // This is to guarantee that children is always a Collection and to prevent Eloquent 
            // from hitting on the database looking for the children
            $children = new Collection();
        }

        $comment->setRelation('children', $children);
    });

    return $branch;

}
Run Code Online (Sandbox Code Playgroud)

现在我们的评论全部排序而不会损害数据库,我们可以开始循环播放广告.我更喜欢使用两个文件而不是一个用于循环,所以我可以稍后重用代码.

资源\意见\文章\ show.blade.php

@if (!$comments->isEmpty())
    @include("articles.comments.container", ['comments'=>$comments])
@else
    no comments
@endif
Run Code Online (Sandbox Code Playgroud)

资源\意见\文章\评论\ container.blade.php

@if (!$comments->isEmpty())
    <ul>
    @foreach ($comments as $comment)
        @include('articles.comments.show', ['comment'=>$comment])
    @endforeach
    </ul>
@else
Run Code Online (Sandbox Code Playgroud)

资源\意见\文章\评论\ show.blade.php

<li>
    {{ $comment->message }}

    @if (!$comment->children->isEmpty())
        @include("articles.comments.container", ['comments'=>$comment->children])
    @endif
</li>
Run Code Online (Sandbox Code Playgroud)