1515use BlitzPHP \Database \Connection \BaseConnection ;
1616use BlitzPHP \Database \ConnectionResolver ;
1717use BlitzPHP \Debug \Toolbar \Collectors \BaseCollector ;
18+ use BlitzPHP \Utilities \Date ;
19+ use BlitzPHP \Utilities \String \Text ;
1820
1921/**
2022 * Collecteur pour l'onglet Base de données de la barre d'outils de débogage.
@@ -41,7 +43,7 @@ class DatabaseCollector extends BaseCollector
4143 /**
4244 * {@inheritDoc}
4345 */
44- protected string $ title = 'Database ' ;
46+ protected string $ title = 'Base de donées ' ;
4547
4648 /**
4749 * Tableau de connexions à la base de données.
@@ -52,8 +54,6 @@ class DatabaseCollector extends BaseCollector
5254
5355 /**
5456 * Les instances de requête qui ont été collectées via l'événement DBQuery.
55- *
56- * @var stdClass[]
5757 */
5858 protected static array $ queries = [];
5959
@@ -74,13 +74,24 @@ public static function collect(EventInterface $event)
7474 * @var \BlitzPHP\Database\Result\BaseResult
7575 */
7676 $ result = $ event ->getTarget ();
77- $ config = (object ) config ('toolbar ' );
7877
79- // Fournit la valeur par défaut au cas où elle n'est pas définie
80- $ max = $ config ->max_queries ?: 100 ;
78+ if (count (static ::$ queries ) < config ('toolbar.max_queries ' , 100 )) {
79+ $ query = (object ) $ result ->details ();
80+
81+ $ backtrace = debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS );
82+
83+ if (! is_cli ()) {
84+ // lorsqu'ils sont appelés dans le navigateur, les deux premiers tableaux de traces
85+ // proviennent du déclencheur d'événement de la base de données, qui ne sont pas nécessaires
86+ $ backtrace = array_slice ($ backtrace , 2 );
87+ }
8188
82- if (count (static ::$ queries ) < $ max ) {
83- static ::$ queries [] = (object ) $ result ->details ();
89+ static ::$ queries [] = [
90+ 'query ' => $ query ,
91+ 'string ' => $ query ->sql ,
92+ 'duplicate ' => in_array ($ query ->sql , array_column (static ::$ queries , 'string ' , null ), true ),
93+ 'trace ' => $ backtrace ,
94+ ];
8495 }
8596 }
8697
@@ -93,20 +104,20 @@ protected function formatTimelineData(): array
93104
94105 foreach ($ this ->connections as $ alias => $ connection ) {
95106 $ data [] = [
96- 'name ' => 'Connecting to Database : " ' . $ connection ->getDatabase () . '". Config: " ' . $ alias . '" ' ,
97- 'component ' => 'Database ' ,
107+ 'name ' => 'Connexion à la base de données : " ' . $ connection ->getDatabase () . '". Config: " ' . $ alias . '" ' ,
108+ 'component ' => 'Base de données ' ,
98109 'start ' => $ connection ->getConnectStart (),
99110 'duration ' => $ connection ->getConnectDuration (),
100111 ];
101112 }
102113
103114 foreach (static ::$ queries as $ query ) {
104115 $ data [] = [
105- 'name ' => 'Query ' ,
106- 'component ' => 'Database ' ,
107- 'query ' => $ query ->sql ,
108- 'start ' => $ query ->start ,
109- 'duration ' => $ query ->duration ,
116+ 'name ' => 'Requête ' ,
117+ 'component ' => 'Base de données ' ,
118+ 'query ' => $ query[ ' query ' ] ->sql ,
119+ 'start ' => $ query[ ' query ' ] ->start ,
120+ 'duration ' => $ query[ ' query ' ] ->duration ,
110121 ];
111122 }
112123
@@ -118,64 +129,57 @@ protected function formatTimelineData(): array
118129 */
119130 public function display (): array
120131 {
121- // Mots clés que nous voulons mettre en gras
122- $ highlight = [
123- 'SELECT ' ,
124- 'DISTINCT ' ,
125- 'FROM ' ,
126- 'WHERE ' ,
127- 'AND ' ,
128- 'INNER JOIN ' ,
129- 'LEFT JOIN ' ,
130- 'RIGHT JOIN ' ,
131- 'JOIN ' ,
132- 'ORDER BY ' ,
133- 'ASC ' ,
134- 'DESC ' ,
135- 'GROUP BY ' ,
136- 'LIMIT ' ,
137- 'INSERT ' ,
138- 'INTO ' ,
139- 'VALUES ' ,
140- 'UPDATE ' ,
141- 'OR ' ,
142- 'HAVING ' ,
143- 'OFFSET ' ,
144- 'NOT IN ' ,
145- 'IN ' ,
146- 'NOT LIKE ' ,
147- 'LIKE ' ,
148- 'COUNT ' ,
149- 'MAX ' ,
150- 'MIN ' ,
151- 'ON ' ,
152- 'AS ' ,
153- 'As ' ,
154- 'AVG ' ,
155- 'SUM ' ,
156- 'UPPER ' ,
157- 'LOWER ' ,
158- '( ' ,
159- ') ' ,
160- ];
132+ $ data = [];
133+ $ data ['view ' ] = __NAMESPACE__ . '\Views\database.tpl ' ;
134+ $ data ['queries ' ] = array_map (function (array $ query ): array {
135+ $ isDuplicate = $ query ['duplicate ' ] === true ;
161136
162- $ data = [
163- 'queries ' => [],
164- ];
137+ $ firstNonSystemLine = '' ;
165138
166- foreach (static ::$ queries as $ query ) {
167- $ sql = $ query ->sql ;
139+ foreach ($ query ['trace ' ] as $ index => &$ line ) {
140+ // simplifier le fichier et la ligne
141+ if (isset ($ line ['file ' ])) {
142+ $ line ['file ' ] = clean_path ($ line ['file ' ]) . ': ' . $ line ['line ' ];
143+ unset($ line ['line ' ]);
144+ } else {
145+ $ line ['file ' ] = '[internal function] ' ;
146+ }
147+
148+ // trouver la première ligne de trace qui ne provient pas du systeme
149+ if ($ firstNonSystemLine === '' && ! Text::contains ($ line ['file ' ], ['SYST_PATH ' , 'BLITZ_PATH ' ])) {
150+ $ firstNonSystemLine = $ line ['file ' ];
151+ }
152+
153+ // simplifier l'appel de fonction
154+ if (isset ($ line ['class ' ])) {
155+ $ line ['function ' ] = $ line ['class ' ] . $ line ['type ' ] . $ line ['function ' ];
156+ unset($ line ['class ' ], $ line ['type ' ]);
157+ }
158+
159+ if (strrpos ($ line ['function ' ], '{closure} ' ) === false ) {
160+ $ line ['function ' ] .= '() ' ;
161+ }
162+
163+ $ line ['function ' ] = str_repeat (chr (0xC2 ) . chr (0xA0 ), 8 ) . $ line ['function ' ];
168164
169- foreach ($ highlight as $ term ) {
170- $ sql = str_replace ($ term , "<strong> {$ term }</strong> " , $ sql );
165+ // ajouter une numérotation d'index complétée par un espace insécable
166+ $ indexPadded = str_pad (sprintf ('%d ' , $ index + 1 ), 3 , ' ' , STR_PAD_LEFT );
167+ $ indexPadded = preg_replace ('/\s/ ' , chr (0xC2 ) . chr (0xA0 ), $ indexPadded );
168+
169+ $ line ['index ' ] = $ indexPadded . str_repeat (chr (0xC2 ) . chr (0xA0 ), 4 );
171170 }
172171
173- $ data ['queries ' ][] = [
174- 'duration ' => (number_format ($ query ->duration , 5 ) * 1000 ) . ' ms ' ,
175- 'sql ' => $ sql ,
176- 'affected_rows ' => $ query ->affected_rows ,
172+ return [
173+ 'hover ' => $ isDuplicate ? 'Cette requête a été appelée plus d \'une fois. ' : '' ,
174+ 'class ' => $ isDuplicate ? 'duplicate ' : '' ,
175+ 'duration ' => (number_format ($ query ['query ' ]->duration , 5 ) * 1000 ) . ' ms ' ,
176+ 'sql ' => $ this ->highlight ($ query ['query ' ]->sql ),
177+ 'affected_rows ' => $ query ['query ' ]->affected_rows ,
178+ 'trace ' => $ query ['trace ' ],
179+ 'trace-file ' => $ firstNonSystemLine ,
180+ 'qid ' => md5 ($ query ['query ' ]->sql . Date::now ()->format ('0.u00 U ' )),
177181 ];
178- }
182+ }, static :: $ queries );
179183
180184 return $ data ;
181185 }
@@ -195,16 +199,29 @@ public function getBadgeValue(): int
195199 */
196200 public function getTitleDetails (): string
197201 {
198- return '( ' . count (static ::$ queries ) . ' Queries across ' . ($ countConnection = count ($ this ->connections )) . ' Connection ' .
199- ($ countConnection > 1 ? 's ' : '' ) . ') ' ;
202+ $ this ->getConnections ();
203+
204+ $ queryCount = count (static ::$ queries );
205+ $ uniqueCount = count (array_filter (static ::$ queries , static fn ($ query ): bool => $ query ['duplicate ' ] === false ));
206+ $ connectionCount = count ($ this ->connections );
207+
208+ return sprintf (
209+ '(%d requête%s au total, %s %d unique sur %d connexion%s) ' ,
210+ $ queryCount ,
211+ $ queryCount > 1 ? 's ' : '' ,
212+ $ uniqueCount > 1 ? 'dont ' : '' ,
213+ $ uniqueCount ,
214+ $ connectionCount ,
215+ $ connectionCount > 1 ? 's ' : '' ,
216+ );
200217 }
201218
202219 /**
203220 * {@inheritDoc}
204221 */
205222 public function isEmpty (): bool
206223 {
207- return empty ( static ::$ queries) ;
224+ return static ::$ queries === [] ;
208225 }
209226
210227 /**
@@ -222,4 +239,53 @@ private function getConnections()
222239 {
223240 $ this ->connections = ConnectionResolver::getConnections ();
224241 }
242+
243+ private function highlight (string $ statement ): string
244+ {
245+ // Liste des mots-clés à mettre en gras
246+ $ replacements = array_map (fn ($ term ) => "<strong> {$ term }</strong> " , $ search = [
247+ 'SELECT ' ,
248+ 'DISTINCT ' ,
249+ 'FROM ' ,
250+ 'WHERE ' ,
251+ 'AND ' ,
252+ 'INNER JOIN ' ,
253+ 'LEFT JOIN ' ,
254+ 'NATURAL JOIN ' ,
255+ 'RIGHT JOIN ' ,
256+ 'JOIN ' ,
257+ 'ORDER BY ' ,
258+ 'ASC ' ,
259+ 'DESC ' ,
260+ 'GROUP BY ' ,
261+ 'LIMIT ' ,
262+ 'INSERT ' ,
263+ 'INTO ' ,
264+ 'VALUES ' ,
265+ 'UPDATE ' ,
266+ 'OR ' ,
267+ 'HAVING ' ,
268+ 'OFFSET ' ,
269+ 'NOT IN ' ,
270+ 'IN ' ,
271+ 'IS NOT NULL ' ,
272+ 'IS NULL ' ,
273+ 'NOT LIKE ' ,
274+ 'LIKE ' ,
275+ 'COUNT ' ,
276+ 'MAX ' ,
277+ 'MIN ' ,
278+ 'ON ' ,
279+ 'AS ' ,
280+ 'As ' ,
281+ 'AVG ' ,
282+ 'SUM ' ,
283+ 'UPPER ' ,
284+ 'LOWER ' ,
285+ '( ' ,
286+ ') ' ,
287+ ]);
288+
289+ return strtr ($ statement , array_combine ($ search , $ replacements ));
290+ }
225291}
0 commit comments