I have a laravel website that lists "submissions" much like reddit. I use this example to more easily understand this problem.
When a user visits the home page, for example, he'll see 30 submissions listed.
Each submission represents a lot of information. Sure there's information from the submission itself, like the title and whatnot. But there's things like "save". For each submission, there must be a query to see if that user hasn't saved the submission, or else it would display "unsave".
Blade:
@if (!Auth::user()->hasSavedSubmission($submission))
<a href="{{ route('save.submission', ['ID' => $submission->id, 'token' => $submission->token]) }}">Save</a>
@else
<a href="{{ route('unsave.submission', ['ID' => $submission->id, 'token' => $submission->token]) }}">Unsave</a>
@endif
User Model:
public function hasSavedSubmission(Submission $submission) {
return (bool) $submission->savedSubmissions->where('user_id', $this->id)->count();
}
Which then requires a query. But there isn't just hasSavedSubmission
, there's a query to see if the user has upvoted/downvoted a submission, or whether or not they've subscribed to that sub, etc..
It gets even worse on comment pages. Let's say I load a comments page with 200 comments. Well, to see if you've saved a comment or voted on a comment, that's 2 queries per comment, making it a total of 400 queries.
Is this normal? Is this good practice, or should I be optimizing this somehow to reduce queries, and how?
A lot of queries are not bad per se, but in your case they can be reduced greatly by adjusting the way you query your database. Currently you query the saved submissions for a each submission seperately, you could alter it so you'll retrieve all saved submissions for a user in just one query.
As an example you could do something like this in your controller:
$query = SavedSubmissions::where('user_id', Auth::user()->id);
$submissionsForUser = $query->get('id'); // only load columns you'll need also saves a bit
// Pass $submissionsForUser to your blade template
In your blade template
@if (!submissionsForUser->contains($submission->id)
<a href="{{ route('save.submission', ['ID' => $submission->id, 'token' => $submission->token]) }}">Save</a>
@else
<a href="{{ route('unsave.submission', ['ID' => $submission->id, 'token' => $submission->token]) }}">Unsave</a>
@endif
Alternativly you could move this logic for retrieving the submissions to the User
model, but that's not very clean.
Other ways to reduce the amount of queries are things like:
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.