Skip to content
Merged

Dev #120

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 8 additions & 22 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,27 @@ jobs:
strategy:
fail-fast: false
matrix:
php: ['8.4', '8.3', '8.2', '8.1', '8.0']
laravel: ['8.*', '9.*', '10.*', '11.*', '12.*']
php: ['8.4', '8.3', '8.2', '8.1']
laravel: ['10.*', '11.*', '12.*', '13.*']
dependency-version: [prefer-stable]
exclude:
- php: 8.0
laravel: 10.*
- php: 8.0
laravel: 11.*
- php: 8.0
laravel: 12.*
- php: 8.1
laravel: 11.*
- php: 8.1
laravel: 12.*
- php: 8.1
laravel: 13.*
- php: 8.2
laravel: 8.*
- php: 8.3
laravel: 8.*
- php: 8.3
laravel: 9.*
- php: 8.4
laravel: 8.*
- php: 8.4
laravel: 9.*
laravel: 13.*
include:
- laravel: 8.*
testbench: 6.23
- laravel: 9.*
testbench: 7.*
- laravel: 10.*
testbench: 8.*
- laravel: 11.*
testbench: 9.*
- laravel: 12.*
testbench: 10.*
- laravel: 13.*
testbench: 11.*

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} - ubuntu-latest

Expand All @@ -71,4 +57,4 @@ jobs:
composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction

- name: Execute tests
run: vendor/bin/phpunit
run: vendor/bin/phpunit
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
],
"require": {
"php": "^7.1 || ^8.0",
"illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0 || ^11.0 || ^12.0"
"illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0"
},
"require-dev": {
"laravel/legacy-factories": "^1.0",
"orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0|^8.0 || ^9.0 || ^10.0",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0 || ^10.5 || ^11.5.3"
"orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0 || ^10.5 || ^11.5.3 || ^12.5.12"
},
"autoload": {
"psr-4": {
Expand Down
45 changes: 34 additions & 11 deletions src/Outputs/Debugbar.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

namespace BeyondCode\QueryDetector\Outputs;

use DebugBar\DataCollector\MessagesCollector;
use Illuminate\Support\Collection;
use Symfony\Component\HttpFoundation\Response;

use Barryvdh\Debugbar\Facade as LaravelDebugbarV3;
use DebugBar\DataCollector\MessagesCollector;
use Fruitcake\LaravelDebugbar\Facades\Debugbar as LaravelDebugbar;

class Debugbar implements Output
{
protected $collector;
Expand All @@ -17,26 +14,52 @@ public function boot()
{
$this->collector = new MessagesCollector('N+1 Queries');

if (class_exists(\Fruitcake\LaravelDebugbar\Facades\Debugbar::class)) {
if (!LaravelDebugbar::hasCollector($this->collector->getName())) {
LaravelDebugbar::addCollector($this->collector);
}
$facade = $this->resolveDebugbarFacade();

if ($facade === null) {
return;
}

if (!LaravelDebugbarV3::hasCollector($this->collector->getName())) {
LaravelDebugbarV3::addCollector($this->collector);
if (! $facade::hasCollector($this->collector->getName())) {
$facade::addCollector($this->collector);
}
}

public function output(Collection $detectedQueries, Response $response)
{
foreach ($detectedQueries as $detectedQuery) {
$this->collector->addMessage(sprintf('Model: %s => Relation: %s - You should add `with(%s)` to eager-load this relation.',
$this->collector->addMessage(sprintf(
'Model: %s => Relation: %s - You should add `with(%s)` to eager-load this relation.',
$detectedQuery['model'],
$detectedQuery['relation'],
$detectedQuery['relation']
));
}
}

/**
* Resolve the installed Debugbar facade at runtime.
*
* Supports barryvdh/laravel-debugbar (v3 and v4+) and
* fruitcake/laravel-debugbar. Returns the first class
* that the autoloader can locate, or null if none exist.
*
* @return string|null
*/
protected function resolveDebugbarFacade()
{
$candidates = [
'Barryvdh\Debugbar\Facades\Debugbar',
'Barryvdh\Debugbar\Facade',
'Fruitcake\LaravelDebugbar\Facades\Debugbar',
];

foreach ($candidates as $candidate) {
if (class_exists($candidate)) {
return $candidate;
}
}

return null;
}
}
48 changes: 16 additions & 32 deletions tests/QueryDetectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

class QueryDetectorTest extends TestCase
{
/** @test */
public function it_detects_n1_query_on_properties()
public function test_it_detects_n1_query_on_properties()
{
Route::get('/', function (){
$authors = Author::all();
Expand All @@ -34,8 +33,7 @@ public function it_detects_n1_query_on_properties()
$this->assertSame('profile', $queries[0]['relation']);
}

/** @test */
public function it_detects_n1_query_on_multiple_requests()
public function test_it_detects_n1_query_on_multiple_requests()
{
Route::get('/', function (){
$authors = Author::get();
Expand All @@ -62,8 +60,7 @@ public function it_detects_n1_query_on_multiple_requests()
$this->assertSame('profile', $queries[0]['relation']);
}

/** @test */
public function it_does_not_detect_a_false_n1_query_on_multiple_requests()
public function test_it_does_not_detect_a_false_n1_query_on_multiple_requests()
{
Route::get('/', function (){
$authors = Author::with("profile")->get();
Expand All @@ -82,8 +79,7 @@ public function it_does_not_detect_a_false_n1_query_on_multiple_requests()
$this->assertCount(0, app(QueryDetector::class)->getDetectedQueries());
}

/** @test */
public function it_ignores_eager_loaded_relationships()
public function test_it_ignores_eager_loaded_relationships()
{
Route::get('/', function (){
$authors = Author::with('profile')->get();
Expand All @@ -100,8 +96,7 @@ public function it_ignores_eager_loaded_relationships()
$this->assertCount(0, $queries);
}

/** @test */
public function it_detects_n1_queries_from_builder()
public function test_it_detects_n1_queries_from_builder()
{
Route::get('/', function (){
$authors = Author::with('profile')->get();
Expand All @@ -123,8 +118,7 @@ public function it_detects_n1_queries_from_builder()
$this->assertSame(Post::class, $queries[0]['relation']);
}

/** @test */
public function it_detects_all_n1_queries()
public function test_it_detects_all_n1_queries()
{
Route::get('/', function (){
$authors = Author::with('profile')->get();
Expand Down Expand Up @@ -154,8 +148,7 @@ public function it_detects_all_n1_queries()
$this->assertSame('author', $queries[1]['relation']);
}

/** @test */
public function it_detects_n1_queries_on_morph_relations()
public function test_it_detects_n1_queries_on_morph_relations()
{
Route::get('/', function (){
foreach (Post::all() as $post) {
Expand All @@ -174,8 +167,7 @@ public function it_detects_n1_queries_on_morph_relations()
$this->assertSame('comments', $queries[0]['relation']);
}

/** @test */
public function it_detects_n1_queries_on_morph_relations_with_builder()
public function test_it_detects_n1_queries_on_morph_relations_with_builder()
{
Route::get('/', function (){
foreach (Post::all() as $post) {
Expand All @@ -194,8 +186,7 @@ public function it_detects_n1_queries_on_morph_relations_with_builder()
$this->assertSame(Comment::class, $queries[0]['relation']);
}

/** @test */
public function it_can_be_disabled()
public function test_it_can_be_disabled()
{
$this->app['config']->set('querydetector.enabled', false);

Expand All @@ -212,8 +203,7 @@ public function it_can_be_disabled()
$this->assertCount(0, $queries);
}

/** @test */
public function it_ignores_whitelisted_relations()
public function test_it_ignores_whitelisted_relations()
{
$this->app['config']->set('querydetector.enabled', true);
$this->app['config']->set('querydetector.except', [
Expand All @@ -235,8 +225,7 @@ public function it_ignores_whitelisted_relations()
$this->assertCount(0, $queries);
}

/** @test */
public function it_ignores_whitelisted_relations_with_attributes()
public function test_it_ignores_whitelisted_relations_with_attributes()
{
$this->app['config']->set('querydetector.enabled', true);
$this->app['config']->set('querydetector.except', [
Expand All @@ -258,8 +247,7 @@ public function it_ignores_whitelisted_relations_with_attributes()
$this->assertCount(0, $queries);
}

/** @test */
public function it_ignores_redirects()
public function test_it_ignores_redirects()
{
Route::get('/', function (){
foreach (Post::all() as $post) {
Expand All @@ -275,8 +263,7 @@ public function it_ignores_redirects()
$this->assertCount(1, $queries);
}

/** @test */
public function it_fires_an_event_if_detects_n1_query()
public function test_it_fires_an_event_if_detects_n1_query()
{
Event::fake();

Expand All @@ -293,8 +280,7 @@ public function it_fires_an_event_if_detects_n1_query()
Event::assertDispatched(QueryDetected::class);
}

/** @test */
public function it_does_not_fire_an_event_if_there_is_no_n1_query()
public function test_it_does_not_fire_an_event_if_there_is_no_n1_query()
{
Event::fake();

Expand All @@ -310,8 +296,7 @@ public function it_does_not_fire_an_event_if_there_is_no_n1_query()

Event::assertNotDispatched(QueryDetected::class);
}
/** @test */
public function it_uses_the_trace_line_to_detect_queries()
public function test_it_uses_the_trace_line_to_detect_queries()
{
Route::get('/', function (){
$authors = Author::all();
Expand All @@ -337,8 +322,7 @@ public function it_uses_the_trace_line_to_detect_queries()
$this->assertSame('profile', $queries[0]['relation']);
}

/** @test */
public function it_empty_queries()
public function test_it_empty_queries()
{
Route::get('/', function (){
$authors = Author::all();
Expand Down
Loading