Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make 'Related To' section based on same Category in laravel

I have a website where i post recipes. each one of them has a category, and i want to display 2-3 more posts with the same category of that post. how can i build a query to display it? i have a Post Model and Category model that has a belongsToMany relation between the two, and it fills a pivot table, that i bind those categories to a post.

This is the function in my BController, this is the function that passes data to the views where users can access and view.

public function slug(Request $request, $slug)

    {
        if (Auth::check()) {
          $fav = DB::table('post_user')->whereUserId(Auth::id())->pluck('post_id')->all();
        }
         /*get search query from slug page*/
        $query=$request->get('q');
        /*display the results of the search*/
        if ($query) {
            $posts = $query ? Post::search($query)
            ->orderBy('id','desc')
            ->paginate(7) : Post::all();
            return view('home', compact('posts','fav'));
        }
       /*the $url veriable is for share buttons*/
           else {
            $url = $request->url();
            $post = Post::where('slug', '=', $slug)->first();
            return view('b.s', compact('post','url'));

        }
    }

this is my Post model:

    public function categories(){
    return $this->belongsToMany('App\Category');
}

this is in Category model:

public function posts(){
    return $this->belongsToMany('App\Post');
}

The pivot table is like so:

            $table->increments('id');
            $table->integer('post_id')->unsigned();

            $table->foreign('post_id')->references('id')
            ->on('posts')->onDelete('cascade');

            $table->integer('category_id')->unsigned()->nullable();
            $table->foreign('category_id')->references('id')
            ->on('categories')->onDelete('cascade');
like image 471
GabMic Avatar asked Dec 25 '16 13:12

GabMic


2 Answers

You can use whereHas to add constraints on related table as:

// get the post usnig slug
$post = Post::where('slug', '=', $slug)->first();

// get the related categories id of the $post
$related_category_ids = $post->categories()->pluck('categories.id');

// get the related post of the categories $related_category_ids
$related_posts = Post::whereHas('categories', function ($q) use($related_category_ids) {
        $q->whereIn('category_id', $related_category_ids)
    })
    ->where('id', '<>', $post->id)
    ->take(3)
    ->get();

Update

Pass the $related_posts to your view and use it as:

@foreach ($related_posts as $related_post)
    <li>{{ related_post->title }}</li>
@endforeach
like image 192
Amit Gupta Avatar answered Oct 21 '22 20:10

Amit Gupta


On possible solution is to include a piece of code to get the required categories.

If I correctly understand your model, you can have several categories. So, we need to take all Categories of your post, and keep only the id ; and we have to exclude the Post ID of the current object :)

$post = Post::where('slug', '=', $slug)->first();

// get Category IDs. There are others ways to do it.
$categoriesId = [];
foreach( $post->categories as $category ) {
  $categoriesId[] = $cateogyr->id;
}

// get similar posts
$others = Post::
     whereIn('categories', $categoriesId)
   ->where('id', '!=', $post->id)
   ->take(3)
   ->get();

In your case, you have a pivot table:

$others = Post::
   with(array('YourPivot' => function($query) use($categoriesId)
     {
       whereIn('categories', $categoriesId)
     })
   ->where('id', '!=', $post->id)
   ->take(3)
   ->get();
like image 38
Georges O. Avatar answered Oct 21 '22 20:10

Georges O.