Profiler

Π”Π°Ρ‚Π° обновлСния ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° 2024-08-01

Profiler

ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ - это ΠΌΠΎΡ‰Π½Ρ‹ΠΉ инструмСнт Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ любого запроса.

Caution

Никогда Π½Π΅ Π²ΠΊΠ»ΡŽΡ‡Π°ΠΉΡ‚Π΅ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ Π² окруТСниях производства, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ ΡΠ΅Ρ€ΡŒΠ΅Π·Π½Ρ‹ΠΌ уязвимостям Π² бСзопасности вашСго ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°.

Установка

Π’ прилоТСниях, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… Symfony Flex , Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ эту ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ Symfony profiler ΠΏΠ΅Ρ€Π΅Π΄ Π΅Π³ΠΎ использованиСм:

1
$ composer require --dev symfony/profiler-pack

Π’Π΅ΠΏΠ΅Ρ€ΡŒ просмотритС Π»ΡŽΠ±ΡƒΡŽ страницу вашСго прилоТСния Π² ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΡƒ ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ. Π—Π°Ρ‚Π΅ΠΌ Ρ‰Π΅Π»ΠΊΠ½ΠΈΡ‚Π΅ Π½Π° любом элСмСнтС ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ, располоТСнной Π² Π½ΠΈΠΆΠ½Π΅ΠΉ части Π²Π°ΡˆΠΈΡ… страниц, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ Π²Π΅Π±-интСрфСйс Symfony Profiler, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° Symfony.

Note

ПанСль инструмСнтов ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ внСдряСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² HTML-ΠΎΡ‚Π²Π΅Ρ‚Ρ‹. Для Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ² содСрТания (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² JSON Π² запросах API) URL ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° доступСн Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ HTTP-ΠΎΡ‚Π²Π΅Ρ‚Π° X-Debug-Token-Link. ΠŸΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ ΠΏΠΎ URL /_profiler, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ всС ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈ.

Note

Для ограничСния объСма памяти, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ профилями Π½Π° дискС, ΠΎΠ½ΠΈ с высокой Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· 2 дня.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ доступ ΠΊ Π΄Π°Π½Π½Ρ‹ΠΌ профилирования

Π’ Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ случаСв, доступ ΠΊ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° ΠΈ Π΅Π΅ Π°Π½Π°Π»ΠΈΠ· осущСствляСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π΅Π³ΠΎ Π²Π΅Π±-интСрфСйса. Однако Π²Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΌ ΠΏΡƒΡ‚Π΅ΠΌ благодаря ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ, прСдоставляСмым сСрвисом ``profiler''.

Если ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΎΡ‚Π²Π΅Ρ‚Π° доступСн, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ loadProfileFromResponse() для доступа ΠΊ ассоциированному с Π½ΠΈΠΌ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŽ:

// ... $profiler - это сСрвис 'profiler' $profile = $profiler->loadProfileFromResponse($response);

Когда ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ сохраняСт Π΄Π°Π½Π½Ρ‹Π΅ ΠΎ запросС, ΠΎΠ½ Ρ‚Π°ΠΊΠΆΠ΅ ассоциируСт с Π½ΠΈΠΌΠΈ Ρ‚ΠΎΠΊΠ΅Π½; этот Ρ‚ΠΎΠΊΠ΅Π½ доступСн Π² HTTP-Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ ΠΎΡ‚Π²Π΅Ρ‚Π° X-Debug-Token. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ этот Ρ‚ΠΎΠΊΠ΅Π½, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŽ любого ΠΏΡ€ΠΎΡˆΠ»ΠΎΠ³ΠΎ ΠΎΡ‚Π²Π΅Ρ‚Π°, благодаря ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ loadProfile():

1
2
$token = $response->headers->get('X-Debug-Token');
$profile = $profiler->loadProfile($token);

Tip

Если ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²ΡˆΠΈΠΊ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½, Π° панСль инструмСнтов Π²Π΅Π±-ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ - Π½Π΅Ρ‚, исслСдуйтС страницу с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ инструмСнтов Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° вашСго Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ HTTP-Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° X-Debug-Token.

БСрвис profiler Ρ‚Π°ΠΊΠΆΠ΅ прСдоставляСт ΠΌΠ΅Ρ‚ΠΎΠ΄ find() для поиска Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² Π½Π° основС Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠ΅Π²:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ послСдниС 10 Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ²
$tokens = $profiler->find('', '', 10, '', '', '');

// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ послСдниС 10 Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² для всСх URL, содСрТащих /admin/
$tokens = $profiler->find('', '/admin/', 10, '', '', '');

// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ послСдниС 10 Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² для всСх URL, Π½Π΅ содСрТащих /api/
$tokens = $profiler->find('', '!/api/', 10, '', '', '');

// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ послСдниС 10 Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² для Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… запросов POST
$tokens = $profiler->find('127.0.0.1', '', 10, 'POST', '', '');

// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ послСдниС 10 Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² для запросов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΈ ΠΎΡ‚ 2 Π΄ΠΎ 4 Π΄Π½Π΅ΠΉ Π½Π°Π·Π°Π΄
$tokens = $profiler->find('', '', 10, '', '4 days ago', '2 days ago');

Π‘Π±ΠΎΡ€Ρ‰ΠΈΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…

ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… сСрвисов, Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… "сборщиками Π΄Π°Π½Π½Ρ‹Ρ…". Symfony поставляСтся с нСсколькими сборщиками, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ запросС, Π»ΠΎΠ³Π³Π΅Ρ€Π΅, ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ, кСшС ΠΈ Ρ‚.Π΄.

Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ эту ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ список сборщиков, Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹Ρ… Π² вашСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ:

1
$ php bin/console debug:container --tag=data_collector

Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ свой собствСнный сборщик Π΄Π°Π½Π½Ρ‹Ρ… , Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ вашим ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ ΠΈΡ… Π½Π° ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΈ Π² Π²Π΅Π±-интСрфСйсС ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°.

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния прилоТСния

Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΈΠ·ΠΌΠ΅Ρ€ΠΈΡ‚ΡŒ врСмя выполнСния Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π·Π°Π΄Π°Ρ‡ Π² вашСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ, Π½Π΅Ρ‚ нСобходимости ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ собствСнный сборщик Π΄Π°Π½Π½Ρ‹Ρ…. ВмСсто этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ встроСнныС ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ для профилирования ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Symfony .

Tip

РассмотритС Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования ΠΏΡ€ΠΎΡ„Π΅ΡΡΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΊΠ°ΠΊ Blackfire, для измСрСния ΠΈ Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π°Π½Π°Π»ΠΈΠ·Π° выполнСния вашСго прилоТСния.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°

Symfony Profiler ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ ΠΈ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ enable() ΠΈ disable() класса Profiler Π² Π²Π°ΡˆΠΈΡ… ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°Ρ…, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠΎΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\HttpKernel\Profiler\Profiler;
// ...

class DefaultController
{
    // ...

    public function someMethod(?Profiler $profiler): Response
    {
        // $profiler Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ установлСн, Ссли вашС ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²ΡˆΠΈΠΊ (ΠΊΠ°ΠΊ prod, ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ)
        if (null !== $profiler) {
            // Ссли ΠΎΠ½ сущСствуСт, ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ для этого ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ дСйствия ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°
            $profiler->disable();
        }

        // ...
    }
}

Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ Π±Ρ‹Π» Π²Π½Π΅Π΄Ρ€Π΅Π½ Π² ваш ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€, Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ псСвдоним, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ Π½Π° ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ сСрвис profiler:

1
2
3
# config/services_dev.yaml
services:
    Symfony\Component\HttpKernel\Profiler\Profiler: '@profiler'

Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° с условиями

ВмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ, ΠΊΠ°ΠΊ объяснялось Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅, ΠΌΠΎΠΆΠ½ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ условия (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ссли ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π² URL):

1
2
3
4
5
# config/packages/dev/web_profiler.yaml
    framework:
        profiler:
            collect: false
            collect_parameter: 'profile'

Π­Ρ‚Π° конфигурация ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ (collect: false), для ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ прилоТСния; Π½ΠΎ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π΅Π³ΠΎ для запросов, содСрТащих ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ запроса с ΠΈΠΌΠ΅Π½Π΅ΠΌ profile (Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ свободно Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ имя этого ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° запроса).

Помимо ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° запроса, эта функция Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΏΡ€ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ΅ поля Ρ„ΠΎΡ€ΠΌΡ‹ с Ρ‚Π°ΠΊΠΈΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ (ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° Π² POST запросах) ΠΈΠ»ΠΈ ΠΏΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΈ Π΅Π³ΠΎ Π² качСствС Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π° запроса.

ОбновлСниС ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов Π²Π΅Π±-ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ послС запросов AJAX

ΠžΠ΄Π½ΠΎΡΡ‚Ρ€Π°Π½ΠΈΡ‡Π½Ρ‹Π΅ прилоТСния (SPA) - это Π²Π΅Π±-прилоТСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ, динамичСски пСрСписывая Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ страницу, Π° Π½Π΅ загруТая Ρ†Π΅Π»Ρ‹Π΅ Π½ΠΎΠ²Ρ‹Π΅ страницы с сСрвСра.

По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, панСль инструмСнтов ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ страницы ΠΈ Π½Π΅ обновляСтся послС ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ запроса AJAX. Однако Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Symfony-Debug-Toolbar-Replace Π² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ 1 Π² ΠΎΡ‚Π²Π΅Ρ‚Π΅ Π½Π° AJAX-запрос, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ панСль инструмСнтов:

1
$response->headers->set('Symfony-Debug-Toolbar-Replace', 1);

Π’ ΠΈΠ΄Π΅Π°Π»Π΅ этот Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ установлСн Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²ΠΎ врСмя Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, Π° Π½Π΅ для производства. Для этого создайтС подписчика событий ΠΈ ΡΠ»ΡƒΡˆΠ°ΠΉΡ‚Π΅ событиС kernel.response :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelInterface;

// ...

class MySubscriber implements EventSubscriberInterface
{
    public function __construct(
        private KernelInterface $kernel,
    ) {
    }

    // ...

    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$this->kernel->isDebug()) {
            return;
        }

        $request = $event->getRequest();
        if (!$request->isXmlHttpRequest()) {
            return;
        }

        $response = $event->getResponse();
        $response->headers->set('Symfony-Debug-Toolbar-Replace', '1');
    }
}

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ сборщика Π΄Π°Π½Π½Ρ‹Ρ…

Symfony Profiler ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΊΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… классов, Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… сборщиками Π΄Π°Π½Π½Ρ‹Ρ…. Symfony поставляСтся Π² ΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡ‚Π΅ с нСсколькими ΠΈΠ· Π½ΠΈΡ…, Π½ΠΎ Π²Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ свой собствСнный.

Π‘Π±ΠΎΡ€Ρ‰ΠΈΠΊ Π΄Π°Π½Π½Ρ‹Ρ… - это класс PHP, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ DataCollectorInterface. Для удобства, ваши сборщики Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠ³ΡƒΡ‚ Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°ΡΡˆΠΈΡ€ΡΡ‚ΡŒΡΡ ΠΈΠ· класса AbstractDataCollector, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ интСрфСйс ΠΈ прСдоставляСт Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹, Π° Ρ‚Π°ΠΊΠΆΠ΅ свойство $this->data для хранСния собранной ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ.

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ сборщик, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ…Ρ€Π°Π½ΠΈΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ запросС:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/DataCollector/RequestCollector.php
namespace App\DataCollector;

use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class RequestCollector extends AbstractDataCollector
{
    public function collect(Request $request, Response $response, \Throwable $exception = null): void
    {
        $this->data = [
            'method' => $request->getMethod(),
            'acceptable_content_types' => $request->getAcceptableContentTypes(),
        ];
    }
}

Π’ΠΎΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π² классС сборщика Π΄Π°Π½Π½Ρ‹Ρ…:
ΠœΠ΅Ρ‚ΠΎΠ΄ collect():

БохраняСт собранныС Π΄Π°Π½Π½Ρ‹Π΅ Π² Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… свойствах ($this->data, Ссли Π²Ρ‹ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚Π΅ ΠΈΠ· AbstractDataCollector). Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½Ρ‹ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ сСрвисы для сбора Π΄Π°Π½Π½Ρ‹Ρ…, Π²Π½Π΅Π΄Ρ€ΠΈΡ‚Π΅ эти сСрвисы Π² конструктор сборщика Π΄Π°Π½Π½Ρ‹Ρ….

Caution

ΠœΠ΅Ρ‚ΠΎΠ΄ collect() вызываСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·. Он Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для "сбора" Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для "подбирания" Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Ρ‹Π»ΠΈ сохранСны вашим сСрвисом.

Caution

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ сСриализуСт экзСмпляры ΠΊΠΎΠ»Π»Π΅ΠΊΡ‚ΠΎΡ€Π° Π΄Π°Π½Π½Ρ‹Ρ…, Π²Π°ΠΌ Π½Π΅ слСдуСт Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ сСриализованы (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ PDO) ΠΈΠ»ΠΈ Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ свой собствСнный ΠΌΠ΅Ρ‚ΠΎΠ΄ serialize().

ΠœΠ΅Ρ‚ΠΎΠ΄ reset():
ВызываСтся ΠΌΠ΅ΠΆΠ΄Ρƒ запросами, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ состояниС ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΎΠ½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΡ‡ΠΈΡ‰Π°Π΅Ρ‚ содСрТаниС $this->data, Π½ΠΎ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ этот ΠΌΠ΅Ρ‚ΠΎΠ΄ для Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ очистки.
ΠœΠ΅Ρ‚ΠΎΠ΄ getName():
Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ сборщика, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ возвращаСтся FQCN класса сборщика Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ этот ΠΌΠ΅Ρ‚ΠΎΠ΄, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ΅ имя (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, app.request_collector). Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎΠ·ΠΆΠ΅ для доступа ΠΊ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ сборщикС (см. Как ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΌ тСстС), поэтому Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Π΅ΡΡ‚ΡŒ использованиС ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… строк вмСсто строк FQCN.

ΠœΠ΅Ρ‚ΠΎΠ΄ collect() вызываСтся Π²ΠΎ врСмя события kernel.response . Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ доступны Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ·ΠΆΠ΅, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ LateDataCollectorInterface ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ lateCollect(), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ вызываСтся нСпосрСдствСнно ΠΏΠ΅Ρ€Π΅Π΄ сСриализациСй Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ° (Π²ΠΎ врСмя события kernel.terminate ).

Note

Если Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ services.yaml ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ с autoconfigure, Ρ‚ΠΎ Symfony Π½Π°Ρ‡Π½Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ваш сборщик Π΄Π°Π½Π½Ρ‹Ρ… послС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ обновлСния страницы. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ ΠΊΠΎΠ»Π»Π΅ΠΊΡ‚ΠΎΡ€ Π΄Π°Π½Π½Ρ‹Ρ… Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ.

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ шаблонов Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°

Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ, собранная вашим сборщиком Π΄Π°Π½Π½Ρ‹Ρ…, ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½Π° ΠΊΠ°ΠΊ Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов Π²Π΅Π±-ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ, Ρ‚Π°ΠΊ ΠΈ Π² Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ΅. Для этого Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ шаблон Twig, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя нСсколько ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… Π±Π»ΠΎΠΊΠΎΠ².

Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ getTemplate() Π² ваш класс сборщика Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΌΡƒ ΡˆΠ°Π±Π»ΠΎΠ½Ρƒ Twig. Π—Π°Ρ‚Π΅ΠΌ Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ нСсколько Π³Π΅Ρ‚Ρ‚Π΅Ρ€ΠΎΠ², Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Ρ‚ΡŒ ΡˆΠ°Π±Π»ΠΎΠ½Ρƒ доступ ΠΊ собранной ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// src/DataCollector/RequestCollector.php
namespace App\DataCollector;

use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
use Symfony\Component\VarDumper\Cloner\Data;

class RequestCollector extends AbstractDataCollector
{
    // ...

    public static function getTemplate(): ?string
    {
        return 'data_collector/template.html.twig';
    }

    public function getMethod(): string
    {
        return $this->data['method'];
    }

    public function getAcceptableContentTypes(): array
    {
        return $this->data['acceptable_content_types'];
    }

    public function getSomeObject(): Data
    {
        // ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ cloneVar() для сброса собранных Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ΅
        return $this->cloneVar($this->data['method']);
    }
}

Π’ ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ΅ΠΌ случаС Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Π½Π° ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов Π±Π΅Π· прСдоставлСния ΠΏΠ°Π½Π΅Π»ΠΈ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°. Для этого Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊ toolbar ΠΈ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π΄Π²ΡƒΡ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… - icon ΠΈ text:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{# templates/data_collector/template.html.twig #}
{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% block toolbar %}
    {% set icon %}
        {# это содСрТаниС, ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΡ‘Π½Π½ΠΎΠ΅ ΠΊΠ°ΠΊ панСль Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов #}
        <svg xmlns="http://www.w3.org/2000/svg"> ... </svg>
        <span class="sf-toolbar-value">Request</span>
    {% endset %}

    {% set text %}
        {# это содСрТаниС, ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΡ‘Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ ΠΌΡ‹ΡˆΡŒΡŽ Π½Π°
           Π½Π° панСль инструмСнтов #}
        <div class="sf-toolbar-info-piece">
            <b>Method</b>
            <span>{{ collector.method }}</span>
        </div>

        <div class="sf-toolbar-info-piece">
            <b>Accepted content type</b>
            <span>{{ collector.acceptableContentTypes|join(', ') }}</span>
        </div>
    {% endset %}

    {# Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ 'link' установлСнноС ΠΊΠ°ΠΊ 'false', ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ эта панСль Π½Π΅
       ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ Ρ€Π°Π·Π΄Π΅Π» Π² Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ΅ #}
    {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
{% endblock %}

Tip

Иконки Symfony Profiler Π²Ρ‹Π±Ρ€Π°Π½Ρ‹ ΠΈΠ· ΠΈΠΊΠΎΠ½ΠΎΠΊ Tabler, большой ΠΈ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠΉ коллСкция SVG ΠΈΠΊΠΎΠ½ΠΎΠΊ с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ. РСкомСндуСтся Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ эти ΠΈΠΊΠΎΠ½ΠΊΠΈ для Π²Π°ΡˆΠΈΡ… собствСнных ΠΏΠ°Π½Π΅Π»Π΅ΠΉ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ Сдинообразия внСшнСго Π²ΠΈΠ΄Π°.

Tip

ВстроСнныС ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ сборщиков ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ всС свои изобраТСния ΠΊΠ°ΠΊ встроСнныС SVG-Ρ„Π°ΠΉΠ»Ρ‹. Π­Ρ‚ΠΎ позволяСт ΠΈΠΌ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π²Π΅Π·Π΄Π΅ Π±Π΅Π· нСобходимости Π²ΠΎΠ·ΠΈΡ‚ΡŒΡΡ со ссылками Π½Π° Π²Π΅Π±-рСсурсы:

1
2
3
4
{% set icon %}
    {{ include('data_collector/icon.svg') }}
    {# ... #}
{% endset %}

Если панСль инструмСнтов Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, шаблон Twig Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π±Π»ΠΎΠΊΠΈ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{# templates/data_collector/template.html.twig #}
{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% block toolbar %}
    {% set icon %}
        {# ... #}
    {% endset %}

    {% set text %}
        <div class="sf-toolbar-info-piece">
            {# ... #}
        </div>
    {% endset %}

    {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
{% endblock %}

{% block head %}
    {# ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ. Π—Π΄Π΅ΡΡŒ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΡΠ»Π°Ρ‚ΡŒΡΡ Π½Π° ΠΈΠ»ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ вашС собствСнноС содСрТаниС CSS ΠΈ JS. #}
    {# Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ {{ parent() }}, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ стили ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, вмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ ΠΈΡ…. #}
{% endblock %}

{% block menu %}
    {# Π­Ρ‚ΠΎ лСвостороннСС мСню Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΏΡ€ΠΈ использовании полноэкранного ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°. #}
    <span class="label">
        <span class="icon"><img src="..." alt=""/></span>
        <strong>Request</strong>
    </span>
{% endblock %}

{% block panel %}
    {# ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ, для отобраТСния наибольшСго количСства Π΄Π΅Ρ‚Π°Π»Π΅ΠΉ. #}
    <h2>Acceptable Content Types</h2>
    <table>
        <tr>
            <th>Content Type</th>
        </tr>

        {% for type in collector.acceptableContentTypes %}
        <tr>
            <td>{{ type }}</td>
        </tr>
        {% endfor %}
    </table>
{% endblock %}

Π‘Π»ΠΎΠΊΠΈ menu ΠΈ panel ΡΠ²Π»ΡΡŽΡ‚ΡΡ СдинствСнными ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ для опрСдСлСния содСрТимого, ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅ΠΌΠΎΠ³ΠΎ Π½Π° ΠΏΠ°Π½Π΅Π»ΠΈ Π²Π΅Π±-ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, ассоциированного с этим сборщиком Π΄Π°Π½Π½Ρ‹Ρ…. ВсС Π±Π»ΠΎΠΊΠΈ ΠΈΠΌΠ΅ΡŽΡ‚ доступ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ collector.

Note

ПолоТСниС ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠ°Π½Π΅Π»ΠΈ Π½Π° ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов опрСдСляСтся ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ΠΎΠΌ сборщика, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ сборщика Π΄Π°Π½Π½Ρ‹Ρ… Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ.

Note

Если Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ services.yaml ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ с autoconfigure, Ρ‚ΠΎ Symfony Π½Π°Ρ‡Π½Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ вашСго сборщика Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов послС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ обновлСния страницы. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ сборщик Π΄Π°Π½Π½Ρ‹Ρ… Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ.

Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… сборщиков Π΄Π°Π½Π½Ρ‹Ρ…

Если Π²Ρ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ Symfony ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ с Π°Π²Ρ‚ΠΎΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈ Π°Π²Ρ‚ΠΎΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ , Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ явно ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сборщик Π΄Π°Π½Π½Ρ‹Ρ…:

1
2
3
4
5
6
7
8
9
10
11
12
# config/services.yaml
services:
    App\DataCollector\RequestCollector:
        tags:
            -
                name: data_collector
                # Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ²ΠΏΠ°Π΄Π°Ρ‚ΡŒ со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Ρ‘Π½Π½Ρ‹ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ getName()
                id: 'App\DataCollector\RequestCollector'
                # ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ шаблон (ΠΈΠΌΠ΅Π΅Ρ‚ больший ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚, Ρ‡Π΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Ρ‘Π½Π½ΠΎΠ΅ getTemplate())
                template: 'data_collector/template.html.twig'
                # ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ (ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΈΠ»ΠΈ ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ Ρ†Π΅Π»ΠΎΠ΅ число; ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ = 0)
                # priority: 300