首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多层评测系统

多层评测系统
EN

Stack Overflow用户
提问于 2016-01-28 22:45:44
回答 6查看 3.2K关注 0票数 23

我对刀片递归部分视图有困难。除了comment.blade.php文件中的递归之外,一切都可以正常工作。

我知道我需要在@include('articles.comments.comment', $comment)周围使用一个程序来再次调用自己,但我不知道如何调用它。

article_comments表:

代码语言:javascript
复制
id
message
user_id
parent_id
created_at
updated_at

app\Article.php类:

代码语言:javascript
复制
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);
    }

}

app\Comments.php类:

代码语言:javascript
复制
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;
    }

}

app\Http\Controllers\ArticlesController.php

代码语言:javascript
复制
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.');
    }
}

resources\views\articles\show.blade.php

代码语言:javascript
复制
@if (count($comments) > 0)
    <ul>
    @foreach ($comments as $comment)
        @include('articles.comments.comment', ['comment'=>$comment])
    @endforeach
    </ul>
@else
    no comments
@endif

resources\views\articles\comments\comment.blade.php

代码语言:javascript
复制
<li>
    {{ $comment->message }}

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

电流错误:

代码语言:javascript
复制
Invalid argument supplied for foreach() (View: /var/www/dev.example.com/resources/views/articles/comments/comment.blade.php) (View: 
EN

回答 6

Stack Overflow用户

发布于 2016-01-28 23:50:42

你们关系很好。我认为这应该是可行的:

resources\views\articles\show.blade.php

代码语言:javascript
复制
@if (count($comments) > 0)
    <ul>
        @each('articles.comments.comment', $comments, 'comment');
    </ul>
@else
    no comments
@endif

resources\views\articles\comments\comment.blade.php

代码语言:javascript
复制
<li>
    {{ $comment->message }}

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

app\Http\Controllers\ArticlesController.php:

代码语言:javascript
复制
$article = Article::where('permalink', '=', $permalink)->with('comments','comments.author','comments.children')->first();
$comments = $article->comments;
return view('articles.show', compact('article','comments'));
票数 10
EN

Stack Overflow用户

发布于 2016-02-11 01:16:53

首先,我看到您将所有注释放置在一个页面中而不进行任何分页,但是,您将Article模型上的Article方法限制为只有具有parent_id=0的注释才能获得根注释。但是,再看看您的代码,在控制器中,您将缓慢地加载comments.authorcomments.children。请注意,延迟加载只会发生在第一个父注释上,然后,所有子节点都必须执行大量查询才能获得它们之间的关系,方法是急切地加载这些关系。

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

app\Article.php

代码语言:javascript
复制
class Article extends Model {

    // ...

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

}

app\Http\Controllers\ArticlesController.php

代码语言:javascript
复制
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;

}

现在,我们已经对所有的评论进行了排序,而没有对数据库进行惩罚,我们可以开始遍历广告了。我更喜欢使用两个文件而不是一个进行循环,这样以后我就可以重用代码了。

resources\views\articles\show.blade.php

代码语言:javascript
复制
@if (!$comments->isEmpty())
    @include("articles.comments.container", ['comments'=>$comments])
@else
    no comments
@endif

resources\views\articles\comments\container.blade.php

代码语言:javascript
复制
@if (!$comments->isEmpty())
    <ul>
    @foreach ($comments as $comment)
        @include('articles.comments.show', ['comment'=>$comment])
    @endforeach
    </ul>
@else

resources\views\articles\comments\show.blade.php

代码语言:javascript
复制
<li>
    {{ $comment->message }}

    @if (!$comment->children->isEmpty())
        @include("articles.comments.container", ['comments'=>$comment->children])
    @endif
</li>
票数 6
EN

Stack Overflow用户

发布于 2016-02-02 14:41:58

我可能漏掉了什么东西,但在我看来,你的代码太复杂了。例如,您可以在注释模型中添加一个user关系(也可以删除整个count方法):

代码语言:javascript
复制
public function user()
{
    return $this->belongsTo('App\User');
}

然后,每当您需要访问注释的用户id或用户名时,只需调用:

代码语言:javascript
复制
$user_id = $comment->user->id;
$username = $comment->user->username;

那么,您应该能够清理大量的控制器:

代码语言:javascript
复制
$article = Article::where('permalink', '=', $permalink)->first();
$comments = Comments::where('article_id', '=', $article->id)->get();

您的show.blade.php文件应该是正常的。您的comment.blade.php文件可以这样编写:

代码语言:javascript
复制
<li>{{ $comment->message }}</li>
@if ($comment->children->count() > 0)
    <ul>
        @foreach($comment->children as $child)
            @include('articles.comments.comment', $child)
        @endforeach
    </ul>
@endif

我相信您对Invalid argument supplied for foreach()错误的问题与您对评论的原始查询有关。错误应该通过使用适当的关系模型来修正。

另外,如果您需要通过一个node列来计算您的评论的子级,您应该可以这样做:

代码语言:javascript
复制
$comment->children()->where('node', $node)->get()->count();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35073613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档