-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[9.x] Prevent queries during response preparation #45603
[9.x] Prevent queries during response preparation #45603
Conversation
020dd19
to
67c4653
Compare
Maybe a |
1a1ed92
to
ee14a8c
Compare
App::preventBadPractices([
'queriesInBlades',
'envCallsOutsideConfig',
'fullModelPathInPolymorphicRelation',
...
]); |
Question, will this prevent unwanted extra queries in blade too? Something like calling aggregate function from relationship for example: <ul>
@foreach($someModelCollection as $model)
<li>{{ $model->relationship()->count() }}</li>
@endforeach
</ul> |
@Rizky92 yes it will. Given your example, if you had @imanghafoori1 I wouldn't say queries in the view are inherently a bad practice. In certain teams, application sizes, and contexts they are perfectly fine. In others, not so much. |
ee14a8c
to
d733414
Compare
Does this prevent relationships from lazily loading? E.g. @foreach ($user->invoices as $invoice)
...
@endforeach Would that throw if that relation wasn't eagerly loaded? It is an interesting approach because it'll bring more awareness of db performance considerations when rendering views. I hope that this won't be frustrating to debug if it's throwing errors and you can't easily decipher where it came from exactly. This PR kinda reminds me of https://github.com/beyondcode/laravel-query-detector |
Related PR of Octane: laravel/octane#631
The problem
In many contexts, queries within a response object can be problematic and hard to detect. The response object may be a
view()
, aJsonResource
, or something else entirely.Two database queries are run in the following view. For some applications this may be totally fine, while others may find this problematic from a performance / resources / conventions perspective.
The solution
To help applications detect these issues, I propose we introduce a new opt-in mechanism that will throw exceptions when a query is run while the response is being prepared.
Response preparation involves the following code:
framework/src/Illuminate/Routing/Router.php
Lines 885 to 914 in c0affdd
If an exception is thrown while the response is passing through this method, an exception will be thrown.
This means apps can throw if a query occurs in a blade view, as seen above, or while a
JsonResource
is being resolved. The following resource would throw an exception.As soon as this resource is a collection, like in a
UserResource
that includes all the users teams, this will trigger a query for every team included in the resource.There are other places where "response preparation" occurs, such as the exception handler, but this feature does not concern itself with that. It is only related to values returned from a Controller.
Doing it manually
As part of this main feature is a lower level feature for preventing queries for certain parts of an application.
This manual mechanism is handy when an application wants to prevent queries while a view is being prepared manually. Take the following example:
This will allow queries to run when the
toArray
method is called even withpreventQueriesWhilePreparingResponse
in use. In this type of scenario where you are preparing the response yourself you may opt-in to prevent queries: