I'm trying to get the related posts of a post, based on its tags.
My post (id 1) has several tags attached to it, ie tag (id 1-3) this means that my post has 3 tags. Based on those tags, I'd like to show other posts that have this tag(s).
My Tag Model:
<?php namespace Digitus\Base\Model;
class Tag extends \Eloquent{
protected $table = 'tags';
protected $guarded = ['id'];
protected $fillable = ['name'];
public function posts()
{
$this->belongsToMany('Digitus\Base\Model\Post');
}
}
My post model:
<?php namespace Digitus\Base\Model;
class Post extends \Eloquent {
protected $fillable = array('title','body', 'author','slug');
public function user()
{
return $this->belongsTo('Digitus\Base\Model\User', 'author');
}
public function tags()
{
return $this->belongsToMany('Digitus\Base\Model\Tag');
}
public function comments()
{
return $this->belongsToMany('Digitus\Base\Model\Comment');
}
public function categories()
{
return $this->belongsToMany('Digitus\Base\Model\Categorie');
}
}
In my view I currently have:
<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8 panel panel-info">
<p>Gerelateerde berichten:</p>
<?php
$posts = Digitus\Base\Model\Post::all();
$tags = Digitus\Base\Model\Tag::all(); ?>
@foreach($posts as $post)
@foreach($post->tags as $tag)
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
@endforeach
@endforeach
</div>
But it doesn't really show the posts which have the same tags, it just throws all my posts out. Also, I tried adding some sort of filter to it, so there won't be any duplicate posts (same post show up 2+ times) but this also failed at my end.
I'm not looking for direct answers, more for directions and suggestions etc.
In this code:
@foreach($posts as $post)
@foreach($post->tags as $tag)
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
@endforeach
@endforeach
you are iterating over all tags of all posts, and outputting the post title.
So for a post that has 3 tags, you will output the post title 3 times.
What you might do is this:
<?php $posts = Digitus\Base\Model\Post::with('Tags.Posts')->get(); ?>
@foreach ($posts as $post)
@foreach ($post->tags as $tag)
@foreach ($tag->posts as $relatedPost)
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $relatedPost->title }}</div>
@endforeach
@endforeach
@endforeach
Not tested, but as far as I understand how Eloquent eager loading works, it should work.
EDIT:
The above would output all posts actually, so if you want the related posts of a single post, this is the way to go:
The following should output an array with a single post in it:
<?php $posts = Digitus\Base\Model\Post::with('tags.posts')->where('id', $id)->get(); ?>
which you then 'iterate' over:
@foreach ($posts as $post)
@foreach ($post->tags as $tag)
@foreach ($tag->posts as $relatedPost)
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $relatedPost->title }}</div>
@endforeach
@endforeach
@endforeach
This will do, but mind there will be run 3 db queries, so maybe you'd like some joins instead
<?php
// don't do this in the view, better in controller, service or whatever and just pass $posts to the view
$posts = Digitus\Base\Model\Post::with('tags.posts')->get();
?>
@foreach($posts as $parentPost)
@foreach($parentPost->tags as $tag)
@foreach($tag->posts as $post)
<?php if($post->id == $parentPost->id) continue; ?>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
@endforeach
@endforeach
@endforeach
----- edit: In your Tag model you don't return nothing from relation, so just add return:
public function posts()
{
return $this->belongsToMany('Digitus\Base\Model\Post');
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.