1
0
mirror of https://github.com/maximebf/php-debugbar.git synced 2025-03-15 19:59:41 +01:00

Upgrade PDOCollector and queries widget (#581)

This commit is contained in:
erikn69 2024-02-10 05:00:41 -05:00 committed by GitHub
parent ff2b6d6346
commit 912691590f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 157 additions and 25 deletions

View File

@ -7,6 +7,7 @@ use DebugBar\DataCollector\PDO\PDOCollector;
$pdo = new TraceablePDO(new PDO('sqlite::memory:'));
$debugbar->addCollector(new PDOCollector($pdo));
$debugbar['pdo']->setDurationBackground();
$pdo->exec('create table users (name varchar)');
$stmt = $pdo->prepare('insert into users (name) values (?)');

View File

@ -20,6 +20,8 @@ class PDOCollector extends DataCollector implements Renderable, AssetProvider
protected $sqlQuotationChar = '<>';
protected $durationBackground = false;
/**
* @param \PDO $pdo
* @param TimeDataCollector $timeCollector
@ -43,6 +45,16 @@ class PDOCollector extends DataCollector implements Renderable, AssetProvider
$this->sqlQuotationChar = $quotationChar;
}
/**
* Enable/disable the shaded duration background on queries
*
* @param bool $enabled
*/
public function setDurationBackground($enabled = true)
{
$this->durationBackground = $enabled;
}
/**
* @return bool
*/
@ -156,11 +168,29 @@ class PDOCollector extends DataCollector implements Renderable, AssetProvider
}
}
$totalTime = $pdo->getAccumulatedStatementsDuration();
if ($this->durationBackground && $totalTime > 0) {
// For showing background measure on Queries tab
$start_percent = 0;
foreach ($stmts as $i => $stmt) {
if (!isset($stmt['duration'])) {
continue;
}
$width_percent = $stmt['duration'] / $totalTime * 100;
$stmts[$i] = array_merge($stmt, [
'start_percent' => round($start_percent, 3),
'width_percent' => round($width_percent, 3),
]);
$start_percent += $width_percent;
}
}
return array(
'nb_statements' => count($stmts),
'nb_failed_statements' => count($pdo->getFailedExecutedStatements()),
'accumulated_duration' => $pdo->getAccumulatedStatementsDuration(),
'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($pdo->getAccumulatedStatementsDuration()),
'accumulated_duration' => $totalTime,
'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($totalTime),
'memory_usage' => $pdo->getMemoryUsage(),
'memory_usage_str' => $this->getDataFormatter()->formatBytes($pdo->getPeakMemoryUsage()),
'peak_memory_usage' => $pdo->getPeakMemoryUsage(),

View File

@ -34,7 +34,8 @@ div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before,
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before {
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before,
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:before {
font-family: PhpDebugbarFontAwesome;
margin-right: 4px;
font-size: 12px;
@ -57,6 +58,15 @@ div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before {
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before {
content: "\f0c5";
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:before {
content: "\f08e";
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link {
color: #888;
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-editor-link:hover {
color: #aaaaaa;
}
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params {
display: none;
width: 70%;
@ -116,3 +126,28 @@ div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar a.phpdebugbar
background: #eee;
color: #888;
}
div.phpdebugbar-widgets-sqlqueries a.phpdebugbar-widgets-duplicates {
font-weight: bold;
text-decoration: underline;
}
div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item div.phpdebugbar-widgets-bg-measure {
position: absolute;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
}
div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-bg-measure div.phpdebugbar-widgets-value {
position: absolute;
height: 100%;
opacity: 0.2;
background: red;
}
div.phpdebugbar-widgets-sqlqueries td.phpdebugbar-widgets-value li.phpdebugbar-widgets-table-list-item {
text-align: left;
padding-left: 6px;
}
div.phpdebugbar-widgets-sqlqueries .phpdebugbar-text-muted {
color: #888;
}

View File

@ -50,15 +50,47 @@
};
select(code);
},
renderList: function (caption, icon, data) {
var $ul = $('<ul />').addClass(csscls('table-list')), $parts;
var $li = $('<li />').addClass(csscls('table-list-item'));
var $span = $('<span />').addClass('phpdebugbar-text-muted');
for (var key in data) {
var value = typeof data[key] === 'function' ? data[key].name + ' {}' : data[key];
$li.clone().append(typeof value === 'object' && value !== null
? [$span.clone().text(value.index || key).append('.'), '&nbsp;']
.concat(value.namespace ? [value.namespace + '::'] : [])
.concat([value.name || value.file])
.concat(value.line ? [$span.clone().text(':' + value.line)] : [])
: [$span.clone().text(key + ':'), '&nbsp;', value]
).appendTo($ul);
}
caption += icon ? ' <i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>' : '';
return $('<tr />').append(
$('<td />').addClass(csscls('name')).html(caption),
$('<td />').addClass(csscls('value')).append($ul)
);
},
render: function() {
this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el);
this.$toolbar = $('<div></div>').addClass(csscls('toolbar')).appendTo(this.$el);
this.$toolbar = $('<div />').addClass(csscls('toolbar')).appendTo(this.$el);
var filters = [], self = this;
this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, stmt) {
if (stmt.type === 'transaction') {
$('<strong />').addClass(csscls('sql')).addClass(csscls('name')).text(stmt.sql).appendTo(li);
} else {
$('<code />').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li);
}
if (stmt.width_percent) {
$('<div />').addClass(csscls('bg-measure')).append(
$('<div />').addClass(csscls('value')).css({
left: stmt.start_percent + '%',
width: Math.max(stmt.width_percent, 0.01) + '%',
})
).appendTo(li);
}
if (stmt.duration_str) {
$('<span title="Duration" />').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li);
}
@ -92,6 +124,7 @@
li.addClass(csscls('error'));
li.append($('<span />').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message));
}
if ((!stmt.type || stmt.type === 'query') && stmt.show_copy !== false) {
$('<span title="Copy to clipboard" />')
.addClass(csscls('copy-clipboard'))
.css('cursor', 'pointer')
@ -100,14 +133,31 @@
event.stopPropagation();
})
.appendTo(li);
}
if (stmt.xdebug_link) {
$('<a href="' + stmt.xdebug_link.url + '"></a>').on('click', function (event) {
event.stopPropagation();
if (stmt.xdebug_link.ajax){
event.preventDefault();
$.ajax(stmt.xdebug_link.url);
}
}).addClass(csscls('editor-link')).appendTo(li);
}
var table = $('<table></table>').addClass(csscls('params'));
if (stmt.params && !$.isEmptyObject(stmt.params)) {
var table = $('<table><tr><th colspan="2">Params</th></tr></table>').addClass(csscls('params')).appendTo(li);
for (var key in stmt.params) {
if (typeof stmt.params[key] !== 'function') {
table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
'">' + stmt.params[key] + '</td></tr>');
self.renderList('Params', 'thumb-tack', stmt.params).appendTo(table);
}
if (stmt.bindings && !$.isEmptyObject(stmt.bindings)) {
self.renderList('Bindings', 'thumb-tack', stmt.bindings).appendTo(table);
}
if (stmt.hints && !$.isEmptyObject(stmt.hints)) {
self.renderList('Hints', 'question-circle', stmt.hints).appendTo(table);
}
if (stmt.backtrace && !$.isEmptyObject(stmt.backtrace)) {
self.renderList('Backtrace', 'list-ul', stmt.backtrace).appendTo(table);
}
if (table.find('tr').length) {
table.appendTo(li);
li.css('cursor', 'pointer').click(function() {
if (table.is(':visible')) {
table.hide();
@ -121,17 +171,26 @@
this.bindAttr('data', function(data) {
// the PDO collector maybe is empty
if (data.length <= 0) {
if (data.length <= 0 || !data.statements) {
return false;
}
this.$list.set('data', data.statements);
this.$status.empty();
// Search for duplicate statements.
for (var sql = {}, unique = 0, duplicate = 0, i = 0; i < data.statements.length; i++) {
for (var sql = {}, duplicate = 0, i = 0; i < data.statements.length; i++) {
if (data.statements[i].type && data.statements[i].type !== 'query') {
continue;
}
var stmt = data.statements[i].sql;
if (data.statements[i].params && !$.isEmptyObject(data.statements[i].params)) {
stmt += ' {' + $.param(data.statements[i].params, false) + '}';
stmt += JSON.stringify(data.statements[i].params);
}
if (data.statements[i].bindings && !$.isEmptyObject(data.statements[i].bindings)) {
stmt += JSON.stringify(data.statements[i].bindings);
}
if (data.statements[i].connection) {
stmt += '@' + data.statements[i].connection;
}
sql[stmt] = sql[stmt] || { keys: [] };
sql[stmt].keys.push(i);
@ -144,8 +203,6 @@
this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i])
.addClass(csscls('sql-duplicate'));
}
} else {
unique++;
}
}
@ -155,7 +212,16 @@
}
if (duplicate) {
t.append(", " + duplicate + " of which were duplicates");
t.append(", " + unique + " unique");
t.append(", " + (data.nb_statements - duplicate) + " unique. ");
// add toggler for displaying only duplicated queries
var duplicatedText = 'Show only duplicated';
$('<a />').addClass(csscls('duplicates')).click(function () {
$(this).toggleClass('shown-duplicated')
.text($(this).hasClass('shown-duplicated') ? 'Show All' : duplicatedText);
$('.' + self.className + ' .' + csscls('list-item'))
.not('.' + csscls('sql-duplicate')).toggle();
}).text(duplicatedText).appendTo(t);
}
if (data.accumulated_duration_str) {
this.$status.append($('<span title="Accumulated duration" />').addClass(csscls('duration')).text(data.accumulated_duration_str));