Nette Documentation Preview

syntax
Создание расширений Tracy
*************************

<div class=perex>

Tracy - отличный инструмент для отладки вашего приложения. Однако иногда вам может понадобиться, чтобы под рукой была и другая информация. Мы покажем, как написать собственные расширения для Tracy Bar, чтобы разработка стала ещё приятнее.

- Создание собственной панели Tracy Bar
- Создание собственного расширения для красного экрана

</div>

.[tip]
Хранилище готовых расширений для Tracy вы найдёте на "Componette":https://componette.org/search/tracy.


Расширения Tracy Bar
====================

Создать новое расширение для Tracy Bar просто. Создайте объект, реализующий интерфейс `Tracy\IBarPanel`, у которого есть два метода: `getTab()` и `getPanel()`. Эти методы должны вернуть HTML-код вкладки (небольшой ярлык, отображаемый прямо на панели Bar) и панели (всплывающее окно, отображаемое после щелчка по вкладке). Если `getPanel()` ничего не вернёт, отобразится только сама вкладка. Если ничего не вернёт `getTab()`, не отобразится ничего вообще, и `getPanel()` вызван не будет.

```php
class ExamplePanel implements Tracy\IBarPanel
{
	public function getTab()
	{
		return /* ... */;
	}

	public function getPanel()
	{
		return /* ... */;
	}
}
```


Регистрация
-----------

Регистрация выполняется вызовом `Tracy\Debugger::getBar()->addPanel()`:

```php
Tracy\Debugger::getBar()->addPanel(new ExamplePanel);
```

Как вариант, панель можно зарегистрировать прямо в конфигурации приложения:

```neon
tracy:
	bar:
		- ExamplePanel
```


HTML-код вкладки
----------------

Должен выглядеть примерно так:

```latte
<span title="Поясняющая подсказка">
	<svg>...</svg>
	<span class="tracy-label">Заголовок</span>
</span>
```

Изображение должно быть в формате SVG. Если поясняющая подсказка не нужна, внешний `<span>` можно опустить.


HTML-код панели
---------------

Должен выглядеть примерно так:

```latte
<h1>Заголовок</h1>

<div class="tracy-inner">
<div class="tracy-inner-container">
	... содержимое ...
</div>
</div>
```

Заголовок должен либо совпадать с заголовком вкладки, либо содержать дополнительные сведения.

Помните, что одно расширение может быть зарегистрировано несколько раз, возможно с разными настройками. Поэтому для оформления нельзя использовать CSS-идентификаторы, только классы, желательно в формате `tracy-addons-<ИмяКласса>[-<необязательное>]`. Добавьте этот класс к div вместе с классом `tracy-inner`. При написании CSS полезно предварять селекторы `#tracy-debug .ваш-класс`, потому что так правило получает более высокую специфичность, чем сбрасывающие стили.


Стили по умолчанию
------------------

В панели у элементов `<a>`, `<table>`, `<pre>` и `<code>` есть заранее заданные стили. Если вы хотите сделать ссылку, скрывающую и показывающую другой элемент, свяжите их атрибутами `href` и `id` и классом `tracy-toggle`:

```latte
<a href="#tracy-addons-ClassName-{$counter}" class="tracy-toggle">Подробности</a>

<div id="tracy-addons-ClassName-{$counter}">...</div>
```

Если состояние по умолчанию - свёрнутое, добавьте обоим элементам класс `tracy-collapsed`.

Используйте статический счётчик, чтобы на одной странице не появились одинаковые идентификаторы.


Собственные ресурсы
-------------------

Если вашей панели нужны собственные стили или скрипт, вы можете попросить Tracy загрузить дополнительные файлы вместе с её собственными ресурсами:

```php
Tracy\Debugger::$customCssFiles[] = __DIR__ . '/panel.css';
Tracy\Debugger::$customJsFiles[] = __DIR__ . '/panel.js';
```


Поддержка AI-агентов .{data-version:2.12.0}
-------------------------------------------

Когда браузером управляет AI-агент, Tracy отправляет в JS-консоль markdown-сводку панели Tracy Bar. Собственные панели могут предоставить свой markdown, добавив в свою реализацию `IBarPanel` метод `getAgentInfo(): ?string`:

```php
class DatabasePanel implements Tracy\IBarPanel
{
	public function getTab(): string { /* ... */ }
	public function getPanel(): string { /* ... */ }

	public function getAgentInfo(): ?string
	{
		return "## Database\n\n- Queries: {$this->count}\n- Total time: {$this->time} ms\n";
	}
}
```

Возвращённый markdown включается в markdown-сводку панели. Если метода нет или он возвращает `null`, панель в сводку не попадает.

Полную картину смотрите в разделе [Интеграция Tracy с AI-агентами |guide#Поддержка AI-агентов].


Расширения красного экрана
==========================

Таким образом вы можете добавить собственные способы отображения исключений или панели, которые появятся на красном экране.

Расширение создаётся так:
```php
Tracy\Debugger::getBlueScreen()->addPanel(function (?Throwable $e) { // перехваченное исключение
	return [
		'tab' => '...Заголовок...',
		'panel' => '...HTML-содержимое панели...',
	];
});
```

Функция вызывается дважды. Сначала в параметре `$e` передаётся само исключение (если оно произошло), и возвращённая панель отрисовывается в начале страницы. Если она вернёт `null` или пустой массив, панель не отрисовывается. Затем функция вызывается с `$e = null`, и возвращённая панель отрисовывается под стеком вызовов. Если функция вернёт в массиве `'bottom' => true`, панель отрисуется в самом низу.

Кроме панелей, через `addAction()` можно добавить и **действия** - кликабельные ссылки или кнопки, которые появятся в шапке страницы с ошибкой рядом со встроенными (например, *search*):

```php
Tracy\Debugger::getBlueScreen()->addAction(function (Throwable $e): ?array {
	if ($e instanceof MyException) {
		return [
			'link' => 'https://example.com/help?code=' . $e->getCode(),
			'label' => 'посмотреть справку',
		];
	}
	return null;
});
```

Callback получает перехваченное исключение и возвращает массив с ключами `link` и `label` либо `null`, если для данного исключения не хочет добавлять действие.


Действие create file .{data-version:2.9.0}
------------------------------------------

Когда вы на странице с ошибкой щёлкнете по файлу, которого ещё нет, Tracy предложит его создать (действие *create file*). Начальное содержимое такого файла можно задать, зарегистрировав генератор:

```php
Tracy\Debugger::getBlueScreen()->addFileGenerator(function (string $file, ?string $class): ?string {
	if (str_ends_with($file, 'Test.php')) {
		return "<?php\n\nclass $class extends Tester\\TestCase\n{\n\t\$END\$\n}\n";
	}
	return null;
});
```

Callback получает путь к целевому файлу и, если оно известно, имя класса, который в нём должен быть определён. Он возвращает начальное содержимое (маркер `$END$` обозначает место, куда встанет курсор, и из вывода удаляется) либо `null`, чтобы оставить решение другому генератору. Генераторы пробуются начиная с зарегистрированного последним; встроенный генератор порождает простой каркас PHP.


Файберы и генераторы .{data-version:2.9.2}
------------------------------------------

Если исключение выброшено в момент, когда файбер или генератор приостановлен, его стек не входит в обычный стек вызовов. Tracy автоматически показывает стек файберов и генераторов, достижимых из исключения, но тот, который работает независимо, остался бы без внимания. Вы можете добавить его в BlueScreen вручную:

```php
Tracy\Debugger::getBlueScreen()->addFiber($fiber);
```

Создание расширений Tracy

Tracy – отличный инструмент для отладки вашего приложения. Однако иногда вам может понадобиться, чтобы под рукой была и другая информация. Мы покажем, как написать собственные расширения для Tracy Bar, чтобы разработка стала ещё приятнее.

  • Создание собственной панели Tracy Bar
  • Создание собственного расширения для красного экрана

Хранилище готовых расширений для Tracy вы найдёте на Componette.

Расширения Tracy Bar

Создать новое расширение для Tracy Bar просто. Создайте объект, реализующий интерфейс Tracy\IBarPanel, у которого есть два метода: getTab() и getPanel(). Эти методы должны вернуть HTML-код вкладки (небольшой ярлык, отображаемый прямо на панели Bar) и панели (всплывающее окно, отображаемое после щелчка по вкладке). Если getPanel() ничего не вернёт, отобразится только сама вкладка. Если ничего не вернёт getTab(), не отобразится ничего вообще, и getPanel() вызван не будет.

class ExamplePanel implements Tracy\IBarPanel
{
	public function getTab()
	{
		return /* ... */;
	}

	public function getPanel()
	{
		return /* ... */;
	}
}

Регистрация

Регистрация выполняется вызовом Tracy\Debugger::getBar()->addPanel():

Tracy\Debugger::getBar()->addPanel(new ExamplePanel);

Как вариант, панель можно зарегистрировать прямо в конфигурации приложения:

tracy:
	bar:
		- ExamplePanel

HTML-код вкладки

Должен выглядеть примерно так:

<span title="Поясняющая подсказка">
	<svg>...</svg>
	<span class="tracy-label">Заголовок</span>
</span>

Изображение должно быть в формате SVG. Если поясняющая подсказка не нужна, внешний <span> можно опустить.

HTML-код панели

Должен выглядеть примерно так:

<h1>Заголовок</h1>

<div class="tracy-inner">
<div class="tracy-inner-container">
	... содержимое ...
</div>
</div>

Заголовок должен либо совпадать с заголовком вкладки, либо содержать дополнительные сведения.

Помните, что одно расширение может быть зарегистрировано несколько раз, возможно с разными настройками. Поэтому для оформления нельзя использовать CSS-идентификаторы, только классы, желательно в формате tracy-addons-<ИмяКласса>[-<необязательное>]. Добавьте этот класс к div вместе с классом tracy-inner. При написании CSS полезно предварять селекторы #tracy-debug .ваш-класс, потому что так правило получает более высокую специфичность, чем сбрасывающие стили.

Стили по умолчанию

В панели у элементов <a>, <table>, <pre> и <code> есть заранее заданные стили. Если вы хотите сделать ссылку, скрывающую и показывающую другой элемент, свяжите их атрибутами href и id и классом tracy-toggle:

<a href="#tracy-addons-ClassName-{$counter}" class="tracy-toggle">Подробности</a>

<div id="tracy-addons-ClassName-{$counter}">...</div>

Если состояние по умолчанию – свёрнутое, добавьте обоим элементам класс tracy-collapsed.

Используйте статический счётчик, чтобы на одной странице не появились одинаковые идентификаторы.

Собственные ресурсы

Если вашей панели нужны собственные стили или скрипт, вы можете попросить Tracy загрузить дополнительные файлы вместе с её собственными ресурсами:

Tracy\Debugger::$customCssFiles[] = __DIR__ . '/panel.css';
Tracy\Debugger::$customJsFiles[] = __DIR__ . '/panel.js';

Поддержка AI-агентов

Когда браузером управляет AI-агент, Tracy отправляет в JS-консоль markdown-сводку панели Tracy Bar. Собственные панели могут предоставить свой markdown, добавив в свою реализацию IBarPanel метод getAgentInfo(): ?string:

class DatabasePanel implements Tracy\IBarPanel
{
	public function getTab(): string { /* ... */ }
	public function getPanel(): string { /* ... */ }

	public function getAgentInfo(): ?string
	{
		return "## Database\n\n- Queries: {$this->count}\n- Total time: {$this->time} ms\n";
	}
}

Возвращённый markdown включается в markdown-сводку панели. Если метода нет или он возвращает null, панель в сводку не попадает.

Полную картину смотрите в разделе Интеграция Tracy с AI-агентами.

Расширения красного экрана

Таким образом вы можете добавить собственные способы отображения исключений или панели, которые появятся на красном экране.

Расширение создаётся так:

Tracy\Debugger::getBlueScreen()->addPanel(function (?Throwable $e) { // перехваченное исключение
	return [
		'tab' => '...Заголовок...',
		'panel' => '...HTML-содержимое панели...',
	];
});

Функция вызывается дважды. Сначала в параметре $e передаётся само исключение (если оно произошло), и возвращённая панель отрисовывается в начале страницы. Если она вернёт null или пустой массив, панель не отрисовывается. Затем функция вызывается с $e = null, и возвращённая панель отрисовывается под стеком вызовов. Если функция вернёт в массиве 'bottom' => true, панель отрисуется в самом низу.

Кроме панелей, через addAction() можно добавить и действия – кликабельные ссылки или кнопки, которые появятся в шапке страницы с ошибкой рядом со встроенными (например, search):

Tracy\Debugger::getBlueScreen()->addAction(function (Throwable $e): ?array {
	if ($e instanceof MyException) {
		return [
			'link' => 'https://example.com/help?code=' . $e->getCode(),
			'label' => 'посмотреть справку',
		];
	}
	return null;
});

Callback получает перехваченное исключение и возвращает массив с ключами link и label либо null, если для данного исключения не хочет добавлять действие.

Действие create file

Когда вы на странице с ошибкой щёлкнете по файлу, которого ещё нет, Tracy предложит его создать (действие create file). Начальное содержимое такого файла можно задать, зарегистрировав генератор:

Tracy\Debugger::getBlueScreen()->addFileGenerator(function (string $file, ?string $class): ?string {
	if (str_ends_with($file, 'Test.php')) {
		return "<?php\n\nclass $class extends Tester\\TestCase\n{\n\t\$END\$\n}\n";
	}
	return null;
});

Callback получает путь к целевому файлу и, если оно известно, имя класса, который в нём должен быть определён. Он возвращает начальное содержимое (маркер $END$ обозначает место, куда встанет курсор, и из вывода удаляется) либо null, чтобы оставить решение другому генератору. Генераторы пробуются начиная с зарегистрированного последним; встроенный генератор порождает простой каркас PHP.

Файберы и генераторы

Если исключение выброшено в момент, когда файбер или генератор приостановлен, его стек не входит в обычный стек вызовов. Tracy автоматически показывает стек файберов и генераторов, достижимых из исключения, но тот, который работает независимо, остался бы без внимания. Вы можете добавить его в BlueScreen вручную:

Tracy\Debugger::getBlueScreen()->addFiber($fiber);