Giter Club home page Giter Club logo

laravel-query-detector's Introduction

Laravel N+1 Query Detector

Latest Version on Packagist Build Status Quality Score Total Downloads

The Laravel N+1 query detector helps you to increase your application's performance by reducing the number of queries it executes. This package monitors your queries in real-time, while you develop your application and notify you when you should add eager loading (N+1 queries).

Example alert

Installation

You can install the package via composer:

composer require beyondcode/laravel-query-detector --dev

The package will automatically register itself.

Documentation

You can find the documentation on our website.

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

laravel-query-detector's People

Contributors

agus24 avatar arubacao avatar braunson avatar bsn4 avatar danielbreves avatar erikverbeek avatar jackwh avatar janpio avatar johannesschobel avatar jvdovec avatar laravel-shift avatar liamjoc avatar liyu001989 avatar marcmascort avatar matthewnessworthy avatar matthewtrask avatar mechelon avatar mikemand avatar misenhower avatar mpociot avatar mr-feek avatar perturbatio avatar plakhin avatar pr3d4dor avatar pyr0hu avatar robburley avatar scottzirkel avatar stevelacey avatar stevemoretz avatar xengine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-query-detector's Issues

"Illegal offset type in isset or empty"

I am running Laravel 5.6 project via Homestead on Win10. Just installed your package:

$ composer require beyondcode/laravel-query-detector --dev
Using version ^0.2.1 for beyondcode/laravel-query-detector
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing beyondcode/laravel-query-detector (0.2.1): Downloading (100%)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: barryvdh/laravel-debugbar
Discovered Package: beyondcode/laravel-query-detector
Discovered Package: fideloper/proxy
Discovered Package: laracasts/generators
Discovered Package: laravel/tinker
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
$

Now I am getting this on all requests:

ErrorException thrown with message "Illegal offset type in isset or empty"

Stacktrace:
#30 ErrorException in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Container/Container.php:1081
#29 Illuminate\Foundation\Bootstrap\HandleExceptions:handleError in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Container/Container.php:1081
#28 Illuminate\Container\Container:getAlias in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:728
#27 Illuminate\Foundation\Application:make in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:119
#26 app in /home/vagrant/projects/projectname/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php:175
#25 BeyondCode\QueryDetector\QueryDetector:applyOutput in /home/vagrant/projects/projectname/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php:189
#24 BeyondCode\QueryDetector\QueryDetector:output in /home/vagrant/projects/projectname/vendor/beyondcode/laravel-query-detector/src/QueryDetectorMiddleware.php:36
#23 BeyondCode\QueryDetector\QueryDetectorMiddleware:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#22 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#21 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php:65
#20 Barryvdh\Debugbar\Middleware\InjectDebugbar:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#19 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#18 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/fideloper/proxy/src/TrustProxies.php:57
#17 Fideloper\Proxy\TrustProxies:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#16 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#15 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php:31
#14 Illuminate\Foundation\Http\Middleware\TransformsRequest:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#13 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#12 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php:31
#11 Illuminate\Foundation\Http\Middleware\TransformsRequest:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#10 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#9 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php:27
#8 Illuminate\Foundation\Http\Middleware\ValidatePostSize:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#7 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#6 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php:51
#5 Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode:handle in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:151
#4 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
#3 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:104
#2 Illuminate\Pipeline\Pipeline:then in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:151
#1 Illuminate\Foundation\Http\Kernel:sendRequestThroughRouter in /home/vagrant/projects/projectname/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:116
#0 Illuminate\Foundation\Http\Kernel:handle in /home/vagrant/projects/projectname/public/index.php:55

Removing your package again fixes the issue:

$ composer remove beyondcode/laravel-query-detector
beyondcode/laravel-query-detector could not be found in require but it is present in require-dev
Do you want to remove it from require-dev [yes]? yes
Dependency "laravel/framework" is also a root requirement, but is not explicitly whitelisted. Ignoring.
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 0 updates, 1 removal
  - Removing beyondcode/laravel-query-detector (0.2.1)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: barryvdh/laravel-debugbar
Discovered Package: fideloper/proxy
Discovered Package: laracasts/generators
Discovered Package: laravel/tinker
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
$

Can I provide any other information?

[Question] How to use this in an API application

Dear @mpociot ,

this is a question regarding how to use this package within an API-style application (e.g., that has no (graphical) UI, but rather outputs data as JSON).

From what i understand, I would guess, one would need to provide its own Output class, right?
Would it be possible to provide a JsonOutput class for this purpose?

If so, would you accept a PR to add this feature?
All the best, cheers

config file publishing doesn't work

Running php artisan vendor:publish --provider=BeyondCode\\QueryDetector\\QueryDetectorServiceProvider doesn't create the config file. Yet, the console says 'Publishing complete.'

Undefined offset: 0

version: 1.7.0

laravel version: 5.8.38

{
    "message": "Undefined offset: 0",
    "exception": "ErrorException",
    "file": "/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php",
    "line": 78,
    "trace": [
        {
            "file": "/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php",
            "line": 78,
            "function": "handleError",
            "class": "Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
            "type": "->"
        },
        {
            "file": "/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php",
            "line": 28,
            "function": "logQuery",
            "class": "BeyondCode\\QueryDetector\\QueryDetector",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php",
            "line": 347,
            "function": "BeyondCode\\QueryDetector\\{closure}",
            "class": "BeyondCode\\QueryDetector\\QueryDetector",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php",
            "line": 196,
            "function": "Illuminate\\Events\\{closure}",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Connection.php",
            "line": 828,
            "function": "dispatch",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Connection.php",
            "line": 682,
            "function": "event",
            "class": "Illuminate\\Database\\Connection",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Connection.php",
            "line": 635,
            "function": "logQuery",
            "class": "Illuminate\\Database\\Connection",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Connection.php",
            "line": 333,
            "function": "run",
            "class": "Illuminate\\Database\\Connection",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php",
            "line": 2130,
            "function": "select",
            "class": "Illuminate\\Database\\Connection",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php",
            "line": 2118,
            "function": "runSelect",
            "class": "Illuminate\\Database\\Query\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php",
            "line": 2604,
            "function": "Illuminate\\Database\\Query\\{closure}",
            "class": "Illuminate\\Database\\Query\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php",
            "line": 2119,
            "function": "onceWithColumns",
            "class": "Illuminate\\Database\\Query\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 521,
            "function": "get",
            "class": "Illuminate\\Database\\Query\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 505,
            "function": "getModels",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 506,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 155,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php",
            "line": 144,
            "function": "get",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 569,
            "function": "getEager",
            "class": "Illuminate\\Database\\Eloquent\\Relations\\Relation",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php",
            "line": 538,
            "function": "eagerLoadRelation",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php",
            "line": 491,
            "function": "eagerLoadRelations",
            "class": "Illuminate\\Database\\Eloquent\\Builder",
            "type": "->"
        },
        {
            "file": "/app/Models/Boming.php",
            "line": 438,
            "function": "load",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php",
            "line": 450,
            "function": "getSectionsAttribute",
            "class": "App\\Models\\Boming",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php",
            "line": 346,
            "function": "mutateAttribute",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php",
            "line": 319,
            "function": "getAttributeValue",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php",
            "line": 1523,
            "function": "getAttribute",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "/app/Models/Boming.php",
            "line": 2354,
            "function": "__get",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php",
            "line": 23,
            "function": "toBoming",
            "class": "App\\Models\\Boming",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Http/Resources/DelegatesToResource.php",
            "line": 132,
            "function": "forwardCallTo",
            "class": "Illuminate\\Http\\Resources\\Json\\JsonResource",
            "type": "->"
        },
        {
            "file": "/app/Http/Resources/Admin/Boming/BomingResource.php",
            "line": 11,
            "function": "__call",
            "class": "Illuminate\\Http\\Resources\\Json\\JsonResource",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/JsonResource.php",
            "line": 94,
            "function": "toArray",
            "class": "App\\Http\\Resources\\Admin\\Boming\\BomingResource",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/ResourceResponse.php",
            "line": 39,
            "function": "resolve",
            "class": "Illuminate\\Http\\Resources\\Json\\JsonResource",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/JsonResource.php",
            "line": 201,
            "function": "toResponse",
            "class": "Illuminate\\Http\\Resources\\Json\\ResourceResponse",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 733,
            "function": "toResponse",
            "class": "Illuminate\\Http\\Resources\\Json\\JsonResource",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 720,
            "function": "toResponse",
            "class": "Illuminate\\Routing\\Router",
            "type": "::"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 680,
            "function": "prepareResponse",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 30,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/Http/Middleware/AdminPermission.php",
            "line": 29,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "App\\Http\\Middleware\\AdminPermission",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php",
            "line": 41,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Routing\\Middleware\\SubstituteBindings",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php",
            "line": 75,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php",
            "line": 49,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\View\\Middleware\\ShareErrorsFromSession",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",
            "line": 56,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Session\\Middleware\\StartSession",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php",
            "line": 37,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php",
            "line": 66,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Cookie\\Middleware\\EncryptCookies",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 104,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 682,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 657,
            "function": "runRouteWithinStack",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 623,
            "function": "runRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 612,
            "function": "dispatchToRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 176,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 30,
            "function": "Illuminate\\Foundation\\Http\\{closure}",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/vendor/beyondcode/laravel-query-detector/src/QueryDetectorMiddleware.php",
            "line": 33,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "BeyondCode\\QueryDetector\\QueryDetectorMiddleware",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php",
            "line": 65,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Barryvdh\\Debugbar\\Middleware\\InjectDebugbar",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/Http/Middleware/LocationMiddleware.php",
            "line": 26,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "App\\Http\\Middleware\\LocationMiddleware",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/Http/Middleware/RobotsMiddleware.php",
            "line": 13,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "App\\Http\\Middleware\\RobotsMiddleware",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/Http/Middleware/LowerCaseRouteMiddleware.php",
            "line": 18,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "App\\Http\\Middleware\\LowerCaseRouteMiddleware",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/fideloper/proxy/src/TrustProxies.php",
            "line": 57,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Fideloper\\Proxy\\TrustProxies",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
            "line": 27,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php",
            "line": 62,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/itsgoingd/clockwork/Clockwork/Support/Laravel/ClockworkMiddleware.php",
            "line": 24,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Clockwork\\Support\\Laravel\\ClockworkMiddleware",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 104,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 151,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 116,
            "function": "sendRequestThroughRouter",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/public/index.php",
            "line": 55,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/server.php",
            "line": 21,
            "function": "require_once"
        }
    ]
}

False detection when using count?

I am using the following code to count a user's open tasks:

$tasks_count = Auth::user()->tasks()->whereCompleted(false)->count();

The plugin tells me:

Model: App\Models\User => Relation: App|Models\Task - You should add "with ('App\Models\Task')" to eager-load this relation.
Model: App\Models\Task => Relation: user - You should add
"with ('user')" to eager-load this relation.

When I do that, the issue still occurs:

$tasks_count = Auth::user()->tasks()->with('user')->whereCompleted(false)->count();

Using

$tasks_count = Auth::user()->with('tasks')->tasks()->whereCompleted(false)->count();

gives me Call to undefined method Illuminate\Database\Eloquent\Builder::tasks() but user has a tasks relationship:

class User extends Authenticatable
{
    // ...

    public function tasks()
    {
        return $this->hasMany('App\Models\Task');
    }

Alert advice text

Just started using this package ❤️

The alert says:

Found the following N+1 queries in this request:

Model: App\Balance => Relation: statement - You should add "with('statement')" to eager-load this relation.

Although it is great that the package tries to give advice (You should add "with('statement')" to eager-load this relation.), this might be "misleading":

What is actually happening in my code is a loop over $account->balances->groupBy('statement_id') (as $balances) where $balances[0]->statement is called. In this case the correct solution was adding $account->load('balances.statement');

Maybe there is a way to formulate the alert in a more code independent way that keeps it useful?

Unable to public the package in Laravel 7

When we run this command

php artisan vendor:publish --provider=BeyondCode\QueryDetector\QueryDetectorServiceProvider
Getting this error
Unable to locate publishable resources.
Could you please help to resolve this issue?

Wrong relation name suggested?

Hi! First of all for your hard work.

When I try to use this package, I get suggestions to fix N+1 problems as expected, but I get results like this:

Model: MyPackage\Products\Models\Product => Relation: OtherPackage\Models\VatRate - You should add with(OtherPackage\Models\VatRate) to eager-load this relation.

This is the relation in Product:

public function vatRate(): BelongsTo
{
    return $this->belongsTo(VatRate::class);
}

When I do that, I get an error (relation does not exist). Why is the package reporting class names instead of relation names? I have been hours trying to figure this out but I have failed. I'm completely sure that I am doing something wrong, but I don't know what it is.

The code is working so I guess that the relation is correct.

Thank you

Error on redirect

Hello there!

I'm submitting data of a form via POST and getting this error:

Argument 1 passed to BeyondCode\QueryDetector\QueryDetector::applyOutput() must be an instance of Illuminate\Http\Response, instance of Illuminate\Http\RedirectResponse given, called in /vendor/beyondcode/laravel-query-detector/src/QueryDetector.php on line 182

I think it's because I return something like return redirect()->route('users.edit', ['user' => $user->uuid]); in my controller... ?

Issue when relation more than one same relation and no results.

Hello, i think i found a issue,

I have this model with 3 relations with Person Model.

and when i filter to show some record without relations with persons the N+1 log shows...

image

But if u see the querie, shows the correct way, its not a N+1 error....
image

this is the n+1 log;
image

Undefined index: object

Hi,

When I try and load my application since installing this, I'm getting "Undefined index: object" on just about every page load.

This error is being triggered by /home/vagrant/sites/mysite/vendor/beyondcode/laravel-query-detector/src/QueryDetector.php on line 60.

As a test, I did dd($relation) just before line 60. The output of the dump is below — as you can see there's no object index. Not sure if this is caused by a quirk in my application, or something in the package?

array:6 [
  "file" => "/home/vagrant/sites/mysite/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php"
  "line" => 550
  "function" => "noConstraints"
  "class" => "Illuminate\Database\Eloquent\Relations\Relation"
  "type" => "::"
  "args" => array:1 [...]
]

Thanks in advance,

Jack

Surface the callstack in other output options

Just discovered in the Debugbar "console" logs (are these actually Laravel logs?) that the package seems to know about the code that is causing the n+1 queries. Whoah!

This should definitely be surfaced in the other Output options as well.

Ability to disable?

Is there any way to disable this, perhaps in a config file or as an environment variable?

I'm getting a false positive and it's super-annoying. I'd rather not have to uninstall it if I can avoid that.

Unnecessary (?) alert

I have a page that is (imo) fully eager loaded:

select * from `users` where `id` = '1' limit 1
select * from `accounts` where `id` = '105' limit 1
select * from `balances` where `balances`.`account_id` in ('105')
select * from `statements` where `statements`.`id` in ('2702', '2703', '2704', '2705', '2706', '2707', '2708', '2709', '2710', '2711', '2712', '2713', '2714', '2715', '2716', '2717', '2718', '2719', '2720')
select * from `transactions` where `transactions`.`statement_id` in ('2702', '2703', '2704', '2705', '2706', '2707', '2708', '2709', '2710', '2711', '2712', '2713', '2714', '2715', '2716', '2717', '2718', '2719', '2720')
select * from `uploads` where `uploads`.`id` in ('2352', '2353', '2354', '2355', '2356', '2357', '2358', '2359', '2360', '2361', '2362', '2363', '2364', '2365', '2366', '2367', '2368', '2369', '2370')
select * from `statements` where `statements`.`account_id` in ('105')
select * from `uploads` where `uploads`.`id` in ('2352', '2353', '2354', '2355', '2356', '2357', '2358', '2359', '2360', '2361', '2362', '2363', '2364', '2365', '2366', '2367', '2368', '2369', '2370')
select * from `transactions` where `transactions`.`account_id` = '105' and `transactions`.`account_id` is not null
select * from `banks` where `banks`.`id` = '36' limit 1
select * from `institutes` where `institutes`.`id` = '1' limit 1

The uploads query is duplicated, but this is caused by different "routes" to the relation. Still the package is giving me an alert:

Model: App\Statement => Relation: App\Upload - You should add "with('AppUpload')" to eager-load this relation.

Could this be a bug or edge case or did I misunderstand something?

How to solve this error?

Hi guys,

I have just installed the package and have already resolved some issues. Unfortunately, I don't know how to solve that:

Found the following N+1 queries in this request:

Model: App\\Domains\\Country\\Models\\Country => Relation: App\\Domains\\Country\\Models\\CountryTranslation - You should add "with(\'App\\Domains\\Country\\Models\\CountryTranslation\')" to eager-load this relation.')

In the place where I call $country, I am already making eager-load like this:

Country::with('translations')->where('abbreviation', '=', $params['code'])->first();

How can I solve that?

In Batch request it is not work properly.

Hii there,

I have created a simple get all details API as a State model. It looks fine in individual API but when I call the same request in batch request it's given me N+1 warning errors:

Individual API Route:

image

Batch Request API Route:

image

Thanks in advance!

False Positive N+1 Queries

Hello, I was testing this package and got right way a false positive, at least, I think.

I have a model Template, and this template has a type, which has a Type model.

I have configured edger loading on Template model to always load Type relations.

Template model:
public $with = ['type'];
public function type() { return $this->hasOne('App\Models\SGC\Contracts\Templates\Types\Type', 'id', 'type_id'); }

When I do, for eg: Contract::with('template')->find(1), I got the error warning N+1 queries and that I should add with('type') to eager load the relation.

Am I doing something wrong?
Thanks.

Support for multiple outputters

Support for multiple output options.

For example I want to alert myself but also write it to a log. Or in later cases write my own output class.

Clockwork Output not working

Class BeyondCode\QueryDetector\Outputs\Clockwork contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (BeyondCode\QueryDetector\Outputs\Output::boot)
When attempting to use the Clockwork output I get this error. After looking at the code I would be more than happy to supply a PR. I would probably convert the interface to an abstract since it seems the only class using the boot method is the Debugbar output class.

If that's a good enough fix (or if you would rather just add the empty boot method instead), I would gladly submit the changes.

Please allow PHP 8

Currently its fixed:

"require": {
      "php": "^7.1",
      "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0"
},
...

And this is why i can't fully upgrade to PHP 8 yet.

Thanks

False detection for different relations with the same values

Let's say you have a Ticket model, the ticket has an assignee, a reporter and a group relation.
The assignee and reporter are both Users. Users also have a group relation, corresponding to a Group model. And a group can be directly assigned to a ticket.

If I want to use the assignee's user group, I would do:
$ticket->assignee->group->name
And for the reporter:
$ticket->reporter->group->name
And for the ticket group itself:
$ticket->group->name

All 3 could have different values, but they could also be the same.

In order to eager load properly, I would use:

Ticket::with([
    'group',
    'reporter.group',
    'assignee.group',
])->get();

If all values are different, there are no issues. So let's say the reporter is a user with the ID of 1, and the assignee is a user with the ID of 20, both user's are in different groups, and the group directly assigned to the ticket is a group that does not belong to one of the users, everything is fine.

However, if the reporter and assignee, are both a user with ID 1, and are therefore in the same group (let's say a group with the ID 100), and the group directly assigned to the ticket is also the group with the ID 100, it will detect a few n+1 queries. Because it will query the same user 2 times (this is detected) and the same group 3 times (this is also a detection).

But these queries should be there, because I am properly eager-loading the relations. They just so happen to have the same values.

In reality even more relations are eager-loaded on the groups and these can also cause n+1 detections, in reality it might look like:

$latestTicket = Ticket::forCompany($company)
    ->with([
        'assignee.group.attributes.labels',
        'assignee.group.attributes.groups.users',

        'reporter.group.attributes.labels',
        'reporter.group.attributes.groups.users',
        
        'group.attributes.labels',
        'group.attributes.groups.users',
    ])
    ->latest()
    ->first();

There seems to be no way to fix this, or am I missing something?

Requests from api - 'N+1 Queries' is already a registered collector

Hi,

In this config :

'output' => [
        \BeyondCode\QueryDetector\Outputs\Debugbar::class
    ]

i got the following exception just when the request cames from the api :

[2018-08-13 15:05:45] local.ERROR: 'N+1 Queries' is already a registered collector {"exception":"[object] (DebugBar\\DebugBarException(code: 0): 'N+1 Queries' is already a registered collector at /var/www/bold/sympl.app2/vendor/maximebf/debugbar/src/DebugBar/DebugBar.php:65)
[stacktrace]

Any ideas ?
CV

Should we need to truncate the queries after out put the queries?

Now, we have a unit test that contains multiple same requests, because we want to test the rate limit.
There is no N+1 problem in a single request, but if we process multiple requests, the N+1 problem will disappear, because, for every request, it will process the queryDetectorMiddleware, and the query count will be increased.

Incompatibility with Laravel 8

I tried to install the package on Laravel 8 and when i try to load a page the error is the following:

Illuminate\Container\Container::bind(): Argument #2 ($concrete) must be of type Closure|string|null

How i can resolve?

Eager loaded pivot relationships still show alert?

Maybe I'm doing something wrong, not sure, but I don't think I've got a N+1 query issue in my case. I still have the alert though.

I have a Section class. We can get the students and/or teachers of a section through properties. Those properties are eager loaded through the $with public variable. Still, the alert shows up.

public function students()
    {
        return $this->belongsToMany(User::class)->wherePivot('type', 'STUDENT');
    }

    public function teachers()
    {
        return $this->belongsToMany(User::class)->wherePivot('type', 'TEACHER');
    }

It happens when I show a section. I get the Section object through the controller method, and just send it back to the view with all eager loaded.

Any idea?

Broken alert text

For a pretty complicated page I am getting this alert:

Model: App\Statement => Relation: App\Upload - You should add "with('AppUpload')" to eager-load this relation.

with('AppUpload') looks broken.

ErrorException QueryDetector.php:78

Hi, thank you for creating awesome package.

I've been facing error while debugging api.

error  Undefined array key 0 Array(1) { userId: 5 } 
ErrorException QueryDetector.php:78

Looking at the source code, I think the cause is that an associative array is returned where an array is expected to be returned, but I'm not sure if I'm using it wrong or not.

$sources = $this->findSource($backtrace);

[Question] Config Except

Dear @mpociot ,

when i read the docs for the config file, i stumbled upon the querydetector.except param and the corresponding comment:

/*
 * Here you can whitelist model relations.
 *
 * Right now, you need to define the model relation both as the class name and the attribute name on the model.
 * So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
 * the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
 */

Why is it that you need to define the relationship name and the corresponding class? Wouldn't the relationship be actually enough? And - if not - wouldn't it be better to define it like this:

'except' => [
   Author::class => [
      'posts' => Post::class,
      'comments' => Comment::class,
   ]
]

in order to properly map the Model to its corresponding relationship?

All the best,
cheers

Can't install with php 7

when i try ti install this package i get the following error message:

[InvalidArgumentException]
Package beyondcode/laravel-query-detector at version has a PHP requirement
incompatible with your PHP version (7.0.2)

Error when upgrading when Laravel 5.6 to Laravel 5.7

beyondcode/laravel-query-detector 0.4.1 requires illuminate/support 5.5.|5.6. -> satisfiable by laravel/framework[v5.6.38, 5.5.x-dev, 5.6.x-dev], illuminate/support[5.5.x-dev, 5.6.x-dev, v5.5.0, v5.5.16, v5.5.17, v5.5.2, v5.5.28, v5.5.33, v5.5.34, v5.5.35, v5.5.36, v5.5.37, v5.5.39, v5.5.40, v5.5.41, v5.5.43, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.25, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9].

Any updates? Thanks.

debug_backtrace limit

Is there a special reason why the debug_backtrace() limit was set to 50?

$backtrace = collect(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 50));

I am in a situation where I am implementing recursive relationships and at a certain depth the following line throws an ErrorException (E_NOTICE) (Undefined offset: 0):

$key = md5($query->sql . $model . $relationName . $sources[0]->name . $sources[0]->line);

Increasing the debug_backtrace() limit makes the notice disappear (at least to a certain depth). Would it be possible to make the limit configurable/disableable or is there a better approach that I don't see right now?

Thank you.

Empty Object will be converted to empty array

Hello,

I discover that while my object is empty, and with the N+1 report for JsonResponse, my empty object will be converted to empty array.
In my production with debug is false will not be converted, this will be ok.
but in my development with debug is true, empty object will be converted to empty array, it's a problem.

example:

    public function index()
    {
        $chapters = Chapter::where('book_id',1)->get();
        $data = [];
        $chapters->each(function (Chapter $chapter) use (&$data) {
            $data['book_name'] = (string) $chapter->book->name;
            $data['empty_object'] = (object) [];
        });
        return response()->json($data);
    }

my expectation output is

{"book_name":"Sunt sit.","empty_object":{},"warning_queries":[...]}

but output is

{"book_name":"Sunt sit.","empty_object":[],"warning_queries":[...]}

In Json.php with namespace BeyondCode\QueryDetector\Outputs

    public function output(Collection $detectedQueries, Response $response)
    {
        if ($response instanceof JsonResponse) {
            $data = $response->getData(true);
            if (! is_array($data)){
                $data = [ $data ];
            }

            $data['warning_queries'] = $detectedQueries;
            $response->setData($data);
        }
    }

change to

    public function output(Collection $detectedQueries, Response $response)
    {
        if ($response instanceof JsonResponse) {
            $data = $response->getData();
            if (! is_array($data)){
                $data = [$data];
            }

            $data['warning_queries'] = $detectedQueries;
            $response->setData($data);
        }
    }

will get my expectation output.

Detecting N1's that already have with() + Namespace issue

For example the code it's alerting on:

return Spark::team()->with('users', 'owner')
                    ->where('id', $id)
                    ->first();

Alert is:

Model: App\Models\Team => Relation: App\Models\User - You should add "with('AppModelsUser')" to eager-load this relation.

Also there seems to be a namespace issue as you can see inside the with above removes the \

Log Output

Hello,

This is a very interesting package and I thank you for it to start off. I do have a question regarding the Log outputs.

I enabled the package and my config looks like so. My Laravel logs were empty.


<?php

return [
    /*
     * Enable or disable the query detection.
     * If this is set to "null", the app.debug config value will be used.
     */
    'enabled' => env('QUERY_DETECTOR_ENABLED', true),

    /*
     * Here you can whitelist model relations.
     *
     * Right now, you need to define the model relation both as the class name and the attribute name on the model.
     * So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
     * the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
     */
    'except' => [
        //Author::class => [
        //    Post::class,
        //    'posts',
        //]
    ],

    /*
     * Define the output formats that you want to use.
     * Available options are:
     *
     * Alert:
     * Displays an alert on the website
     * \BeyondCode\QueryDetector\Outputs\Alert::class
     *
     * Debugbar: (make sure you have the barryvdh/laravel-debugbar package installed)
     * Writes the N+1 queries into a custom messages collector of Debugbar
     * \BeyondCode\QueryDetector\Outputs\Debugbar::class
     *
     * Log:
     * Writes the N+1 queries into the Laravel.log file
     * \BeyondCode\QueryDetector\Outputs\Log::class
     */
    'output' => [
        \BeyondCode\QueryDetector\Outputs\Log::class,
       // \BeyondCode\QueryDetector\Outputs\Alert::class,
    ]
];

Immediately after turning enabled to true my logs started flooding with info leveled entries.

For starters I thought the N+1 entries would be at a warning level and not info. Also is it really nessisary that it logs all this info entries for Pipeline, Routing and Middleware?

Am I misunderstanding something here?

https://imgur.com/l9lX1SM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.