While working on the upcoming https://ohdear.app redesign, I noticed that list that displays all sites of a team was very slow. Let's look at a simplified version of how we fetch the data to build the site list for the current team.
When displaying a site list for teams with 200 sites, 200 extra queries are performed, and this is what makes the site list slow.
Here's the modified code: $sites = Team::current() // returns an instance of the team model ->sites() ->with('team') ->get() ->filter(fn (Site $site) => currentUser()->can('administer', $site)); This successfully solves the N+1 problem.
$team = Team::current(); $team ->sites() ->get() ->map(fn (Site $site) => $site->setRelation('team', $team)) ->filter(fn (Site $site) => currentUser()->can('administer', $site)); By using setRelation, Eloquent will not reach out to the database anymore to get the team relation, it will simply return the Team instance we passed.