Skip to content

Commit cdf0649

Browse files
authored
Merge pull request #104 from Stevemoretz/master
Support multiple requests
2 parents 722c45c + 4aa2269 commit cdf0649

File tree

2 files changed

+72
-8
lines changed

2 files changed

+72
-8
lines changed

src/QueryDetector.php

+24-8
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,29 @@ class QueryDetector
1414
{
1515
/** @var Collection */
1616
private $queries;
17+
/**
18+
* @var bool
19+
*/
20+
private $booted = false;
1721

18-
public function __construct()
22+
private function resetQueries()
1923
{
2024
$this->queries = Collection::make();
2125
}
2226

27+
public function __construct()
28+
{
29+
$this->resetQueries();
30+
}
31+
2332
public function boot()
2433
{
25-
DB::listen(function($query) {
34+
if ($this->booted) {
35+
$this->resetQueries();
36+
return;
37+
}
38+
39+
DB::listen(function ($query) {
2640
$backtrace = collect(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 50));
2741

2842
$this->logQuery($query, $backtrace);
@@ -32,6 +46,8 @@ public function boot()
3246
app()->singleton($outputType);
3347
app($outputType)->boot();
3448
}
49+
50+
$this->booted = true;
3551
}
3652

3753
public function isEnabled(): bool
@@ -52,13 +68,13 @@ public function logQuery($query, Collection $backtrace)
5268
});
5369

5470
// The query is coming from an Eloquent model
55-
if (! is_null($modelTrace)) {
71+
if (!is_null($modelTrace)) {
5672
/*
5773
* Relations get resolved by either calling the "getRelationValue" method on the model,
5874
* or if the class itself is a Relation.
5975
*/
6076
$relation = $backtrace->first(function ($trace) {
61-
return Arr::get($trace, 'function') === 'getRelationValue' || Arr::get($trace, 'class') === Relation::class ;
77+
return Arr::get($trace, 'function') === 'getRelationValue' || Arr::get($trace, 'class') === Relation::class;
6278
});
6379

6480
// We try to access a relation
@@ -81,8 +97,8 @@ public function logQuery($query, Collection $backtrace)
8197

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

84-
$count = Arr::get($this->queries, $key.'.count', 0);
85-
$time = Arr::get($this->queries, $key.'.time', 0);
100+
$count = Arr::get($this->queries, $key . '.count', 0);
101+
$time = Arr::get($this->queries, $key . '.time', 0);
86102

87103
$this->queries[$key] = [
88104
'count' => ++$count,
@@ -110,7 +126,7 @@ protected function findSource($stack)
110126

111127
public function parseTrace($index, array $trace)
112128
{
113-
$frame = (object) [
129+
$frame = (object)[
114130
'index' => $index,
115131
'name' => null,
116132
'line' => isset($trace['line']) ? $trace['line'] : '?',
@@ -195,7 +211,7 @@ protected function getOutputTypes()
195211
{
196212
$outputTypes = config('querydetector.output');
197213

198-
if (! is_array($outputTypes)) {
214+
if (!is_array($outputTypes)) {
199215
$outputTypes = [$outputTypes];
200216
}
201217

tests/QueryDetectorTest.php

+48
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,54 @@ public function it_detects_n1_query_on_properties()
3434
$this->assertSame('profile', $queries[0]['relation']);
3535
}
3636

37+
/** @test */
38+
public function it_detects_n1_query_on_multiple_requests()
39+
{
40+
Route::get('/', function (){
41+
$authors = Author::get();
42+
43+
foreach ($authors as $author) {
44+
$author->profile;
45+
}
46+
});
47+
48+
// first request
49+
$this->get('/');
50+
$queries = app(QueryDetector::class)->getDetectedQueries();
51+
$this->assertCount(1, $queries);
52+
$this->assertSame(Author::count(), $queries[0]['count']);
53+
$this->assertSame(Author::class, $queries[0]['model']);
54+
$this->assertSame('profile', $queries[0]['relation']);
55+
56+
// second request
57+
$this->get('/');
58+
$queries = app(QueryDetector::class)->getDetectedQueries();
59+
$this->assertCount(1, $queries);
60+
$this->assertSame(Author::count(), $queries[0]['count']);
61+
$this->assertSame(Author::class, $queries[0]['model']);
62+
$this->assertSame('profile', $queries[0]['relation']);
63+
}
64+
65+
/** @test */
66+
public function it_does_not_detect_a_false_n1_query_on_multiple_requests()
67+
{
68+
Route::get('/', function (){
69+
$authors = Author::with("profile")->get();
70+
71+
foreach ($authors as $author) {
72+
$author->profile;
73+
}
74+
});
75+
76+
// first request
77+
$this->get('/');
78+
$this->assertCount(0, app(QueryDetector::class)->getDetectedQueries());
79+
80+
// second request
81+
$this->get('/');
82+
$this->assertCount(0, app(QueryDetector::class)->getDetectedQueries());
83+
}
84+
3785
/** @test */
3886
public function it_ignores_eager_loaded_relationships()
3987
{

0 commit comments

Comments
 (0)