我对刀片递归部分视图有困难。除comment.blade.php
文件中的递归外,其他所有内容都适用。
我知道我需要在@include('articles.comments.comment', $comment)
附近使用foreach再次召唤自己,但我不确定如何调用它。
article_comments 表格:
id
message
user_id
parent_id
created_at
updated_at
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);
}
}
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;
}
}
应用\ HTTP \控制器\ 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.');
}
}
资源\视图\物品\ show.blade.php
@if (count($comments) > 0)
<ul>
@foreach ($comments as $comment)
@include('articles.comments.comment', ['comment'=>$comment])
@endforeach
</ul>
@else
no comments
@endif
资源\视图\物品\评论\ 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>
当前错误:
Invalid argument supplied for foreach() (View: /var/www/dev.example.com/resources/views/articles/comments/comment.blade.php) (View:
答案 0 :(得分:10)
你非常接近。我认为这应该有效:
<强>资源\视图\物品\ show.blade.php 强>
@if (count($comments) > 0)
<ul>
@each('articles.comments.comment', $comments, 'comment');
</ul>
@else
no comments
@endif
<强>资源\视图\物品\评论\ comment.blade.php 强>
<li>
{{ $comment->message }}
@if (count($comment->children) > 0)
<ul>
@each('articles.comments.comment', $comment->children, 'comment');
</ul>
@endif
</li>
应用\ 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'));
答案 1 :(得分:6)
首先,我发现您将所有评论都放在一个页面中而没有任何分页,但是,您将comments()
模型上的Article
方法限制为仅{{1}的评论仅获取根注释。但是,进一步查看代码,在控制器中,您需要延迟加载parent_id=0
和comments.author
。请注意,延迟加载仅发生在第一个父注释中,之后,所有子项都必须通过急切加载关系来进行大量查询才能获得关系。
如果您希望将所有评论放在一个页面中,我建议您删除comments.children
约束并一次加载评论并应用策略来订购它们。这是一个例子:
app \ Article.php
parent_id=0
应用\ HTTP \控制器\ ArticlesController.php 强>
class Article extends Model {
// ...
public function comments()
{
return $this->hasMany('App\Comments');
}
}
现在我们的评论全部排序而不会损害数据库,我们可以开始循环播放广告。我更喜欢使用两个文件而不是一个用于循环,所以我可以稍后重用代码。
<强>资源\视图\物品\ show.blade.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;
}
<强>资源\视图\物品\评论\ container.blade.php 强>
@if (!$comments->isEmpty())
@include("articles.comments.container", ['comments'=>$comments])
@else
no comments
@endif
<强>资源\视图\物品\评论\ show.blade.php 强>
@if (!$comments->isEmpty())
<ul>
@foreach ($comments as $comment)
@include('articles.comments.show', ['comment'=>$comment])
@endforeach
</ul>
@else
答案 2 :(得分:2)
我可能会遗漏一些东西,但它看起来像是你复杂了一些代码。例如,您可以为评论模型添加user
关系(您也可以删除整个count
方法):
public function user()
{
return $this->belongsTo('App\User');
}
然后,只要您需要访问评论者的用户ID或用户名,您就可以致电:
$user_id = $comment->user->id;
$username = $comment->user->username;
然后你应该能够清理很多你的控制器:
$article = Article::where('permalink', '=', $permalink)->first();
$comments = Comments::where('article_id', '=', $article->id)->get();
您的show.blade.php
文件应该没问题。
您的comment.blade.php
文件可以这样写:
<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
列计算评论的孩子,您应该可以执行以下操作:
$comment->children()->where('node', $node)->get()->count();
答案 3 :(得分:2)
我简化了一下,但这就是我要做的事情:
雄辩的部分:
class Article extends Model
{
public function comments()
{
return $this->hasMany(Comment::class)->where('parent_id', 0);
}
}
class Comment extends Model
{
public function article()
{
return $this->belongsTo(Article::class);
}
public function children()
{
return $this->hasMany(Comment::class, 'parent_id');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
控制器/路线行动部分:
// Fetching article using your example:
$article = Article::where('permalink', '=', $permalink)->first();
// returning view somewhere below...
查看部分: 文章观点:
@include('comments', ['comments' => $article->comments])
评论观点:
<ul>
@foreach($comments as $comment)
<li>
<h2>{{ $comment->user->name }}</h2>
<p>{{ $comment->message }}</p>
@if(count($comments) > 0)
@include('comments', ['comments' => $comment->children])
@endif
</li>
@endforeach
</ul>
请注意,如果有很多嵌套注释,例如:
,则效率不高Comment
-> Child Comment
-> Child Child Comment
-> Child Child Child Comment
结构化的另一种方法是将所有注释一次性提取:
// Change the relation on the Article Eloquent model:
public function comments()
{
return $this->hasMany(Comment::class);
}
假设parent_id的默认值为0,那么在文章视图中你可以这样做:
@include('comments', ['comments' => $article->comments, 'parent' => 0])
在您的评论视图中,您可以执行以下操作:
<ul>
@foreach($comments as $comment)
@if($parent === (int) $comment->parent_id)
<li>
<h2>{{ $comment->user->name }}</h2>
<p>{{ $comment->message }}</p>
@include('comments', ['comments' => $comments, 'parent' => (int) $comment->id])
</li>
@endif
@endforeach
</ul>
更新: 看看你是如何坚持这一点的,我上传了一个例子:https://github.com/rojtjo/comments-example
确保查看最后一次提交,它显示了我在示例中使用的不同方法之间的差异。
答案 4 :(得分:2)
从mysql数据库开始:
评论表格式
id
commentable_id
commentable_type
parent_id
message
user_id
created_at
updated_at
文章表格结构
id
content
user_id
created_at
updated_at
您的模型将如下设置:注释模型将是多态的,因此您可以在应用程序的其他部分使用您的注释。注意:我建议您将模型移至app\models\
文件夹。
app \ Comments.php 类:
namespace App
class Comments extends \Eloquent {
/**
* Name of the table to use for this model
*
* @var string
*/
protected $table = 'comments';
/**
* The fields that are fillable
*
* @var array
*/
protected $fillable = array(
'commentable_type',
'commentable_id',
'message',
'user_id',
'parent_id'
);
/**
* Commentable: Polymorphic relationship
*
* @return mixed
*/
public function commentable()
{
return $this->morphTo();
}
/**
* User: belongsTo relationship
*
* @return mixed
*/
public function user()
{
return $this->belongsTo('User','user_id');
}
/**
* Parent Comment: belongsTo relationship
*
* @return \App\Comment | null
*/
public function parent()
{
return $this->belongsTo('App\Comments','parent_id');
}
/**
* Children Comment: hasMany relationship
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function children()
{
return $this->hasMany('App\Comments','parent_id');
}
}
app \ Articles.php 类:
namespace App
class Articles extends \Eloquent {
/**
* Name of the table to use for this model
*
* @var string
*/
protected $table = 'articles';
protected $fillable = [
'user_id',
'content'
];
/**
* User: belongsTo relationship
*
* @return mixed
*/
public function user()
{
return $this->belongsTo('User','user_id');
}
/**
* Comments: Polymorphic Relationship
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function comments()
{
return $this->morphMany('App\Comments','commentable');
}
}
文章控制器与添加的代码实际上是相同的,以便加载评论及其子项。
应用\ HTTP \控制器\ ArticlesController.php:强>
namespace App\Http\Controllers;
use App\Articles;
class ArticlesController extends Controller {
/**
* GET: View of an article
*
* @param string $permalink
* @return \Illuminate\View\View
*/
public function getView($permalink)
{
//Let's fetch the article
$article = Articles::where('permalink','=',$permalink)
//Eager load relationships while applying conditions
->with([
'comments' => function($query) {
//Utility method to orderBy 'created_at' DESC
return $query->latest();
},
'comments.children' => function($query) {
//Utility method to orderBy 'created_at' DESC
return $query->latest();
}
])
->first();
//Generate the view
return view('articles.show',['article'=>$article]);
}
}
最后,显示数据的视图
<强>资源\视图\物品\ show.blade.php 强>
<h1>My article:</h1>
<div>
<p>
@if($article)
{{$article->content}}
@endif
</p>
</div>
@if($article)
<!-- Comments: START -->
<div>
@if (count($article->comments) > 0)
<ul>
@foreach ($article->comments as $comment)
@include('articles.comments.comment', ['comment'=>$comment])
@endforeach
</ul>
@else
<span>no comments</span>
@endif
</div>
<!-- Comments: END -->
@endif
<强>资源\视图\物品\评论\ comment.blade.php 强>
<li>
{{ $comment->message }}
<!-- Comment Children: START -->
@if (count($comment->children) > 0)
<ul>
@foreach ($comment->children as $child)
@include('articles.comments.comment', ['comment'=>$child])
@endforeach
</ul>
@endif
<!-- Comment Children: END -->
</li>
答案 5 :(得分:0)
我重构了你的Comments.php。你可以试试这个:
应用\的comments.php 强>
class Comments extends Model {
protected $table = 'article_comments';
protected $fillable = [
'parent_id',
'message',
];
public function children()
{
return $this->hasMany('App\Comments', 'parent_id');
}
public function countChildren($node = null)
{
$query = $this->children();
return (!empty($node)) ? $query->where('node', $node)->count() : $query->count();
}
}
<强>资源\视图\物品\评论\ comment.blade.php 强>
<li>{{ $comment->message }}</li>
@if (App\Comments::find($comment->comment_id)->countChildren() > 0)
<ul>
<li>{{ $comment->message}}</li>
@include('articles.comments.comment', ['comment' => $comment])
</ul>
@endif
<强>资源\视图\物品\ show.blade.php 强>
@if (count($comments) > 0)
<ul>
@foreach ($comments as $comment)
@include('articles.comments.comment', ['comment' => $comment])
@endforeach
</ul>
@else
no comments
@endif