Bicycle/System/Classes/ProfilerToolbar.php
Egor Isaev 9d4edf147a dev
2026-08-07 11:40:03 +03:00

92 lines
3.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* @package Bicycle
* @author Egor Isaev
* @description ProfilerToolbar.php
* @copyright (c) 07/08/2026
*/
namespace System\Classes;
use Services\Auth;
use Services\DataBase\Classes\Profiler;
/**
* Debug-панель внизу страницы: время запроса, память, SQL-запросы
* (см. Services\DataBase\Classes\Profiler). Видна только role === 'admin'
* (см. Services\Auth) — render() отдаёт пустую строку всем остальным.
* Аналог ProfilerToolbar для Kohana (github.com/Alert/profilertoolbar).
*/
class ProfilerToolbar
{
/**
* Рендерит панель, если текущий пользователь — admin, иначе — пустую строку.
*
* @return string
*/
public static function render(): string
{
$user = Auth::instance()->getUser();
if (($user['role'] ?? null) !== 'admin') {
return '';
}
$time_ms = (microtime(true) - ($_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true))) * 1000;
$memory = memory_get_peak_usage(true);
$query_count = Profiler::count();
$query_time = Profiler::totalTime();
$rows = '';
foreach (Profiler::entries() as $entry) {
$rows .= '<tr>' .
'<td>' . number_format($entry['time_ms'], 2) . ' ms</td>' .
'<td><code>' . htmlspecialchars($entry['sql'], ENT_QUOTES, 'UTF-8') . '</code></td>' .
'<td><code>' . htmlspecialchars(json_encode($entry['params'], JSON_UNESCAPED_UNICODE), ENT_QUOTES, 'UTF-8') . '</code></td>' .
'</tr>';
}
return self::html($time_ms, $memory, $query_count, $query_time, $rows);
}
/**
* @param float $time_ms Время выполнения запроса, мс
* @param int $memory Пиковое потребление памяти, байт
* @param int $query_count Число SQL-запросов
* @param float $query_time Суммарное время SQL-запросов, мс
* @param string $rows Готовые <tr> со списком запросов
* @return string
*/
private static function html(float $time_ms, int $memory, int $query_count, float $query_time, string $rows): string
{
$memory_mb = number_format($memory / 1024 / 1024, 2);
$time = number_format($time_ms, 1);
$query_ms = number_format($query_time, 1);
return <<<HTML
<div id="profiler-toolbar" style="position:fixed;left:0;right:0;bottom:0;z-index:99999;
font:12px/1.4 monospace;background:#1b1b1b;color:#ddd;border-top:2px solid #444;">
<div style="display:flex;gap:16px;align-items:center;padding:4px 12px;cursor:pointer;"
onclick="var b=document.getElementById('profiler-toolbar-body');b.style.display=b.style.display==='none'?'block':'none';">
<strong style="color:#8bc34a;">Profiler</strong>
<span>время: {$time} ms</span>
<span>память: {$memory_mb} MB</span>
<span>SQL: {$query_count} ({$query_ms} ms)</span>
</div>
<div id="profiler-toolbar-body" style="display:none;max-height:300px;overflow:auto;border-top:1px solid #444;">
<table style="width:100%;border-collapse:collapse;">
<thead>
<tr style="text-align:left;color:#999;">
<th style="padding:4px 12px;">Время</th>
<th style="padding:4px 12px;">SQL</th>
<th style="padding:4px 12px;">Параметры</th>
</tr>
</thead>
<tbody>{$rows}</tbody>
</table>
</div>
</div>
HTML;
}
}