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

rin4ik's avatar
Level 50

How can I get rid of n+1 problem

I'm using class based composers and don't know how to solve n+1 problem

  public function compose(View $view)
    {
        $view->with('categories', Category::with('posts')->orderBy('title', 'asc')->get());

        $view->with('tags', Tag::all());

        $view->with('popular', Post::orderBy('views', 'desc')->take(3)->get());

        $view->with('featured', Post::where('is_featured', 1)->take(3)->get());

        $view->with('recent', Post::orderBy('date', 'desc')->take(3)->get());
    }
0 likes
12 replies
bobbybouwmann's avatar

Not really sure what you mean with the n+1 problem. Do post have other relationships that you use? If so you can get less queries by doing this

$view->with('featured', Post::with('category')->where('is_featured', 1)->take(3)->get());
1 like
luddinus's avatar

How do you use those variables in your views?

1 like
rin4ik's avatar
Level 50

@bobbybouwmann Yes I have tags and categories relationships. my query results are growing with new posts . code above added additional 4 queries.

rin4ik's avatar
Level 50

@luddinus for example with categories like this

        <aside class="widget border pos-padding shadow">
            <h3 class="widget-title text-uppercase text-center">Категории</h3>
            <ul>
                @foreach($categories as $category)
                <li style='text-transform:uppercase'>
                    <a style="text-decoration:none" href="{{route('category.show',$category->slug)}}">{{$category->title}}</a>
                    <span class="post-count pull-right">{{$category->posts->count()}}</li>
                </span>
                @endforeach

            </ul>
        </aside>

here tags and featured posts

<aside class="widget news-letter shadow ">
            <h3 class="widget-title text-uppercase text-center">Теги</h3>
            <ul>
                @foreach($tags as $tag)

                <a style="text-decoration:none; color:#383636" href="{{route('tag.show',$tag->slug)}}">
                    <li class="form-control" style='text-transform:lowercase;margin-bottom:10px; '>{{$tag->title}}</li>
                </a>
                @endforeach

            </ul>
        </aside>

        <aside class="widget shadow">
            <h3 class="widget-title text-uppercase text-center">Популярные посты</h3>
            @foreach($popular as $item)
            <div class="popular-post">


                <a href="{{route('post.show',$item)}}" class="popular-img">
                    <img src="{{$item->getImage()}}" alt="">

                    <div class="p-overlay"></div>
                </a>

                <div class="p-content">
                    <a href="{{route('post.show',$item)}}" class="text-uppercase">{{$item->title}}</a>
                    <span class="p-date">{{$item->getDate()}}</span>

                </div>
            </div>
            @endforeach
        </aside>
bobbybouwmann's avatar
Level 88

As far as I see it you have 6 queries right now. Unless you access more relations that are not loaded using with in your view. That will bring indeed more queries. You need to select all relationships that are used in your with method to eliminate the query count!

1 like
rin4ik's avatar
Level 50

popular recent and featured posts here

@foreach($popular as $item)
            <div class="popular-post">


                <a href="{{route('post.show',$item)}}" class="popular-img"><img src="{{$item->getImage()}}" alt="">

                    <div class="p-overlay"></div>
                </a>

                <div class="p-content">
                    <a href="{{route('post.show',$item)}}" class="text-uppercase">{{$item->title}}</a>
                    <span class="p-date">{{$item->getDate()}}</span>

                </div>
            </div>
 @endforeach           
        </aside>
   <aside class="widget">
            <h3 class="widget-title text-uppercase text-center">Рекомендованные посты</h3>

            <div id="widget-feature" class="owl-carousel">
              @foreach($featured as $item)
                <div class="item">
                    <div class="feature-content">
                        <img src="{{$item->getImage()}}" width="200px" height="150px" alt="">

                        <a href="{{route('post.show',$item)}}" class="overlay-text text-center">
                            <h5 class="text-uppercase">{{$item->title}}</h5>

                            <p>Lorem ipsum </p>
                        </a>
                    </div>
                </div>
                @endforeach      
            </div>

        </aside>
 <aside class="widget pos-padding shadow">
            <h3 class="widget-title text-uppercase text-center">Недавные посты</h3>

            <div class="thumb-latest-posts">

                @foreach($recent as $item)
                <div class="media">
                    <div class="media-left">
                        <a href="{{route('post.show',$item)}}" class="popular-img"><img src="{{$item->getImage()}}" alt="">
                            <div class="p-overlay"></div>
                        </a>
                    </div>
                    <div class="p-content">
                        <a href="{{route('post.show',$item)}}" class="text-uppercase">{{$item->title}}</a>
                        <span class="p-date">{{$item->getDate()}}</span>
                    </div>
                </div>
                @endforeach
                
            </div>
           
        </aside>
rin4ik's avatar
Level 50

@bobbybouwmann if you mean this line

{{$category->posts->count()}}

I passed it with in my view and it shows only 1 query result that's fine

$view->with('categories', Category::with('posts')->orderBy('title', 'asc')->get());
bobbybouwmann's avatar

This should give you 6 queries, as far as I know! Can you show what queries you get now using the laravel debug bar?

1 like
bobbybouwmann's avatar

How do you assign the view composer to a view right now? It look like the view composer is used in multiple views and therefore you have so much queries. The queries in your view composer are correct!

2 likes

Please or to participate in this conversation.