Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

willD's avatar
Level 1

Add a navigation navigation menu

I new to laravel and I have defined posts and categories on my project. I am trying to implement a dropdown navigation function to display the post on each corresponding category but when I try doing it like this @foreach($posts->items() as $post) it will display every the posts in all the categories instead of being filtered by category but when I try to filter it by category like this @foreach($category->posts as $post) it will not show anything when clicked on it. Here's my code

<div class="block sm:hidden">
    <a href="#" class="block md:hidden text-base font-bold uppercase text-center flex justify-center items-center" @click="open = !open">
        Topics <i :class="open ? 'fa-chevron-down': 'fa-chevron-up'" class="fas ml-2"></i>
    </a>
</div>
<div :class="open ? 'block': 'hidden'" class="w-full flex-grow sm:flex sm:items-center sm:w-auto">
    <div class="w-full container mx-auto flex flex-col sm:flex-row items-center justify-center text-sm font-bold uppercase mt-0 px-6 py-2">
        <a href="{{ route('home') }}" class="hover:bg-gray-400 rounded py-2 px-4 mx-2">Home</a>
        @foreach($categories as $category)
            <div class="relative inline-block text-left" x-data="{ openDropdown: false }">
                <button @click="openDropdown = !openDropdown" type="button" class="hover:bg-gray-400 rounded py-2 px-4 mx-2">
                    {{ $category->title }}  <i :class="openDropdown ? 'fa-chevron-up': 'fa-chevron-down'" class="fas ml-2"></i>
                </button>

                <div x-show="openDropdown" @click.away="openDropdown = false" class="absolute right-0 w-40 mt-2 origin-top-right bg-white border border-gray-300 rounded-md shadow-lg">

                    <!-- Dropdown content -->
                    @foreach($category->posts as $post)
                        <a href="{{ route('view', $post->slug) }}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">{{ $post->title }}</a>
                    @endforeach
                </div>
            </div>
        @endforeach
        <a href="#" class="hover:bg-gray-400 rounded py-2 px-4 mx-2">About us</a>
    </div>
</div>

already check controller and models and seems to me that categories and posts are properly related I do not understand why it will not display the post on each corresponding category here some examples of my models and controls:

Category.php { use HasFactory;

protected $fillable = ['title', 'slug'];

public function posts(): belongsToMany
{
    return $this->belongsToMany(  Post::class);
}

}

Post.php class Post extends Model { use HasFactory; protected $fillable = ['title', 'slug', 'thumbnail', 'body', 'active', 'published_at', 'user_id']; protected $casts = [ 'published_at' => 'datetime' ]; public function user(): BelongsTo { return $this->belongsTo( related: User::class); }

public function categories(): belongsToMany
{
    return $this->belongsToMany(  Category::class);


}

PostController.php class PostController extends Controller {

public function index(): View 
{

    $posts = Post::query()
        ->where('active', '=', 1)
        ->whereDate('published_at', '<', Carbon::now())
        ->orderBy('published_at', 'desc')
        ->paginate(10);

    $categories = Category::query()
        ->leftJoin('category_post', 'categories.id', '=', 'category_post.category_id')
        ->select('categories.title', 'categories.slug', DB::raw('count(*) as total'))
        ->groupBy('categories.id', 'categories.title', 'categories.slug') // Include 'categories.title' in GROUP BY
        ->orderByDesc('total')
        ->limit(5)
        ->get();

        // dd($categories, $categories->toArray(), $posts, $posts->toArray());

    return view('home', compact('posts', 'categories'));
}





public function show(Post $post)
{
    if(!$post->active || $post->published_at > Carbon::now()){
        throw new NotFoundHttpException();
    }

    $next = Post::query()
    ->where('active', true)
    ->whereDate('published_at', '<=', Carbon::now())
    ->whereDate('published_at', '<', $post->published_at)
    ->orderBy('published_at', 'desc')
    ->limit(1)
    ->first();

    $prev = Post::query()
    ->where('active', true)
    ->whereDate('published_at', '<=', Carbon::now())
    ->whereDate('published_at', '<', $post->published_at)
    ->orderBy('published_at', 'asc')
    ->limit(1)
    ->first();


    return view('post.view', compact('post', 'prev', 'next'));
}

public function byCategory(Category $category)
{

    $posts = Post::query()
    ->join('category_post', 'posts.id', '=', 'category_post.post_id')
    ->where('category_post.category_id', '=', $category->id)
    ->where('active', '=', true)
    ->whereDate('published_at', '<=', Carbon::now())
    ->orderBy('published_at', 'desc')
    ->paginate(10);

return view('home', compact('posts'));

} } Also tried this $category->posts()->get() as $post in the loop but did not change any. Any suggestions?

0 likes
1 reply
Snapey's avatar
public function index(): View 
{

    $categories = Category::query()
        ->with('posts', function ($q){
            $q->where('active', true)
                ->whereDate('published_at', '<', Carbon::now())
                ->orderBy('published_at', 'desc')
        })
        ->limit(5)
        ->get();

        // dd($categories, $categories->toArray(), $posts, $posts->toArray());

    return view('home', compact('categories'));
}

Please or to participate in this conversation.