Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0de1c78

Browse files
committed
[DoctrineBridge] Improve queries parameters display in Profiler
1 parent43b753d commit0de1c78

File tree

3 files changed

+168
-21
lines changed

3 files changed

+168
-21
lines changed

‎src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php‎

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
useSymfony\Component\HttpFoundation\Request;
1919
useSymfony\Component\HttpFoundation\Response;
2020
useSymfony\Component\HttpKernel\DataCollector\DataCollector;
21+
useSymfony\Component\VarDumper\Caster\Caster;
22+
useSymfony\Component\VarDumper\Cloner\Stub;
2123

2224
/**
2325
* DoctrineDataCollector.
@@ -121,6 +123,38 @@ public function getName()
121123
return'db';
122124
}
123125

126+
/**
127+
* {@inheritdoc}
128+
*/
129+
protectedfunctiongetCasters()
130+
{
131+
returnparent::getCasters() + [
132+
ObjectParameter::class =>staticfunction (ObjectParameter$o,array$a,Stub$s):array {
133+
$s->class =$o->getClass();
134+
$s->value =$o->getObject();
135+
136+
$r =new \ReflectionClass($o->getClass());
137+
if ($f =$r->getFileName()) {
138+
$s->attr['file'] =$f;
139+
$s->attr['line'] =$r->getStartLine();
140+
}else {
141+
unset($s->attr['file']);
142+
unset($s->attr['line']);
143+
}
144+
145+
if ($error =$o->getError()) {
146+
return [Caster::PREFIX_VIRTUAL.'' =>$error->getMessage()];
147+
}
148+
149+
if ($o->isStringable()) {
150+
return [Caster::PREFIX_VIRTUAL.'__toString()' => (string)$o->getObject()];
151+
}
152+
153+
return [Caster::PREFIX_VIRTUAL.'' =>sprintf('Object of class "%s" could not be converted to string.',$o->getClass())];
154+
},
155+
];
156+
}
157+
124158
privatefunctionsanitizeQueries(string$connectionName,array$queries):array
125159
{
126160
foreach ($queriesas$i =>$query) {
@@ -133,6 +167,7 @@ private function sanitizeQueries(string $connectionName, array $queries): array
133167
privatefunctionsanitizeQuery(string$connectionName,array$query):array
134168
{
135169
$query['explainable'] =true;
170+
$query['runnable'] =true;
136171
if (null ===$query['params']) {
137172
$query['params'] = [];
138173
}
@@ -143,6 +178,7 @@ private function sanitizeQuery(string $connectionName, array $query): array
143178
$query['types'] = [];
144179
}
145180
foreach ($query['params']as$j =>$param) {
181+
$e =null;
146182
if (isset($query['types'][$j])) {
147183
// Transform the param according to the type
148184
$type =$query['types'][$j];
@@ -162,10 +198,14 @@ private function sanitizeQuery(string $connectionName, array $query): array
162198
}
163199
}
164200

165-
list($query['params'][$j],$explainable) =$this->sanitizeParam($param);
201+
list($query['params'][$j],$explainable,$runnable) =$this->sanitizeParam($param,$e);
166202
if (!$explainable) {
167203
$query['explainable'] =false;
168204
}
205+
206+
if (!$runnable) {
207+
$query['runnable'] =false;
208+
}
169209
}
170210

171211
$query['params'] =$this->cloneVar($query['params']);
@@ -180,32 +220,33 @@ private function sanitizeQuery(string $connectionName, array $query): array
180220
* indicating if the original value was kept (allowing to use the sanitized
181221
* value to explain the query).
182222
*/
183-
privatefunctionsanitizeParam($var):array
223+
privatefunctionsanitizeParam($var, ?\Throwable$error):array
184224
{
185225
if (\is_object($var)) {
186-
$className =\get_class($var);
226+
return [newObjectParameter($var,$stringable =method_exists($var,'__toString'),$error),false,$stringable && !$error];
227+
}
187228

188-
returnmethod_exists($var,'__toString') ?
189-
[sprintf('/* Object(%s): */"%s"',$className,$var->__toString()),false] :
190-
[sprintf('/* Object(%s) */',$className),false];
229+
if ($error) {
230+
return [''.$error->getMessage(),false,false];
191231
}
192232

193233
if (\is_array($var)) {
194234
$a = [];
195-
$original =true;
235+
$explainable =$runnable =true;
196236
foreach ($varas$k =>$v) {
197-
list($value,$orig) =$this->sanitizeParam($v);
198-
$original =$original &&$orig;
237+
list($value,$e,$r) =$this->sanitizeParam($v,null);
238+
$explainable =$explainable &&$e;
239+
$runnable =$runnable &&$r;
199240
$a[$k] =$value;
200241
}
201242

202-
return [$a,$original];
243+
return [$a,$explainable,$runnable];
203244
}
204245

205246
if (\is_resource($var)) {
206-
return [sprintf('/* Resource(%s) */',get_resource_type($var)),false];
247+
return [sprintf('/* Resource(%s) */',get_resource_type($var)),false,false];
207248
}
208249

209-
return [$var,true];
250+
return [$var,true,true];
210251
}
211252
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Bridge\Doctrine\DataCollector;
13+
14+
finalclass ObjectParameter
15+
{
16+
private$object;
17+
private$stringable;
18+
private$error;
19+
private$class;
20+
21+
/**
22+
* @param object $object
23+
*/
24+
publicfunction__construct($object,bool$stringable, ?\Throwable$error)
25+
{
26+
$this->object =$object;
27+
$this->stringable =$stringable;
28+
$this->error =$error;
29+
$this->class =\get_class($object);
30+
}
31+
32+
/**
33+
* @return object
34+
*/
35+
publicfunctiongetObject()
36+
{
37+
return$this->object;
38+
}
39+
40+
publicfunctionisStringable():bool
41+
{
42+
return$this->stringable;
43+
}
44+
45+
publicfunctiongetError(): ?\Throwable
46+
{
47+
return$this->error;
48+
}
49+
50+
publicfunctiongetClass():string
51+
{
52+
return$this->class;
53+
}
54+
}

‎src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php‎

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
useSymfony\Component\HttpFoundation\Request;
1919
useSymfony\Component\HttpFoundation\Response;
2020
useSymfony\Component\VarDumper\Cloner\Data;
21+
useSymfony\Component\VarDumper\Dumper\CliDumper;
2122

2223
class DoctrineDataCollectorTestextends TestCase
2324
{
@@ -74,7 +75,7 @@ public function testCollectTime()
7475
/**
7576
* @dataProvider paramProvider
7677
*/
77-
publicfunctiontestCollectQueries($param,$types,$expected,$explainable)
78+
publicfunctiontestCollectQueries($param,$types,$expected,$explainable,bool$runnable =true)
7879
{
7980
$queries = [
8081
['sql' =>'SELECT * FROM table1 WHERE field1 = ?1','params' => [$param],'types' =>$types,'executionMS' =>1],
@@ -83,8 +84,19 @@ public function testCollectQueries($param, $types, $expected, $explainable)
8384
$c->collect(newRequest(),newResponse());
8485

8586
$collectedQueries =$c->getQueries();
86-
$this->assertEquals($expected,$collectedQueries['default'][0]['params'][0]);
87+
88+
$collectedParam =$collectedQueries['default'][0]['params'][0];
89+
if ($collectedParaminstanceof Data) {
90+
$dumper =newCliDumper($out =fopen('php://memory','r+b'));
91+
$dumper->setColors(false);
92+
$collectedParam->dump($dumper);
93+
$this->assertStringMatchesFormat($expected,print_r(stream_get_contents($out, -1,0),true));
94+
}else {
95+
$this->assertEquals($expected,$collectedParam);
96+
}
97+
8798
$this->assertEquals($explainable,$collectedQueries['default'][0]['explainable']);
99+
$this->assertSame($runnable,$collectedQueries['default'][0]['runnable']);
88100
}
89101

90102
publicfunctiontestCollectQueryWithNoParams()
@@ -100,9 +112,11 @@ public function testCollectQueryWithNoParams()
100112
$this->assertInstanceOf(Data::class,$collectedQueries['default'][0]['params']);
101113
$this->assertEquals([],$collectedQueries['default'][0]['params']->getValue());
102114
$this->assertTrue($collectedQueries['default'][0]['explainable']);
115+
$this->assertTrue($collectedQueries['default'][0]['runnable']);
103116
$this->assertInstanceOf(Data::class,$collectedQueries['default'][1]['params']);
104117
$this->assertEquals([],$collectedQueries['default'][1]['params']->getValue());
105118
$this->assertTrue($collectedQueries['default'][1]['explainable']);
119+
$this->assertTrue($collectedQueries['default'][1]['runnable']);
106120
}
107121

108122
publicfunctiontestCollectQueryWithNoTypes()
@@ -134,7 +148,7 @@ public function testReset()
134148
/**
135149
* @dataProvider paramProvider
136150
*/
137-
publicfunctiontestSerialization($param,$types,$expected,$explainable)
151+
publicfunctiontestSerialization($param,$types,$expected,$explainable,bool$runnable =true)
138152
{
139153
$queries = [
140154
['sql' =>'SELECT * FROM table1 WHERE field1 = ?1','params' => [$param],'types' =>$types,'executionMS' =>1],
@@ -144,8 +158,19 @@ public function testSerialization($param, $types, $expected, $explainable)
144158
$c =unserialize(serialize($c));
145159

146160
$collectedQueries =$c->getQueries();
147-
$this->assertEquals($expected,$collectedQueries['default'][0]['params'][0]);
161+
162+
$collectedParam =$collectedQueries['default'][0]['params'][0];
163+
if ($collectedParaminstanceof Data) {
164+
$dumper =newCliDumper($out =fopen('php://memory','r+b'));
165+
$dumper->setColors(false);
166+
$collectedParam->dump($dumper);
167+
$this->assertStringMatchesFormat($expected,print_r(stream_get_contents($out, -1,0),true));
168+
}else {
169+
$this->assertEquals($expected,$collectedParam);
170+
}
171+
148172
$this->assertEquals($explainable,$collectedQueries['default'][0]['explainable']);
173+
$this->assertSame($runnable,$collectedQueries['default'][0]['runnable']);
149174
}
150175

151176
publicfunctionparamProvider()
@@ -156,19 +181,46 @@ public function paramProvider()
156181
[true, [],true,true],
157182
[null, [],null,true],
158183
[new \DateTime('2011-09-11'), ['date'],'2011-09-11',true],
159-
[fopen(__FILE__,'r'), [],'/* Resource(stream) */',false],
160-
[new \stdClass(), [],'/* Object(stdClass) */',false],
184+
[fopen(__FILE__,'r'), [],'/* Resource(stream) */',false,false],
185+
[
186+
new \stdClass(),
187+
[],
188+
<<<EOTXT
189+
{#%d
190+
⚠: "Object of class "stdClass" could not be converted to string."
191+
}
192+
EOTXT
193+
,
194+
false,
195+
false,
196+
],
161197
[
162198
newStringRepresentableClass(),
163199
[],
164-
'/* Object(Symfony\Bridge\Doctrine\Tests\DataCollector\StringRepresentableClass): */"string representation"',
200+
<<<EOTXT
201+
Symfony\Bridge\Doctrine\Tests\DataCollector\StringRepresentableClass {#%d
202+
__toString(): "string representation"
203+
}
204+
EOTXT
205+
,
165206
false,
166207
],
167208
];
168209

169210
if (version_compare(Version::VERSION,'2.6','>=')) {
170-
$tests[] = ['this is not a date', ['date'],'this is not a date',false];
171-
$tests[] = [new \stdClass(), ['date'],'/* Object(stdClass) */',false];
211+
$tests[] = ['this is not a date', ['date'],"⚠ Could not convert PHP value 'this is not a date' of type 'string' to type 'date'. Expected one of the following types: null, DateTime",false,false];
212+
$tests[] = [
213+
new \stdClass(),
214+
['date'],
215+
<<<EOTXT
216+
{#%d
217+
⚠: "Could not convert PHP value of type 'stdClass' to type 'date'. Expected one of the following types: null, DateTime"
218+
}
219+
EOTXT
220+
,
221+
false,
222+
false,
223+
];
172224
}
173225

174226
return$tests;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp