Description
Symfony version(s) affected: 5.2+
Description
Problem 1
Injecting any service into a DataCollector extending AbstractDataCollector
introduced in #37332 causes a silent exception:
Serialization of 'Closure' is not allowed
This is because __sleep
and __wakeup
methods are not implemented there to limit serialization to data
property only. Since AbstractDataCollector
was introduced to reduce boilerplate, it should either extend Symfony\Component\HttpKernel\DataCollector\DataCollector
(implementing __sleep
and adding cloneVar
helper) or implement __sleep
on its own. This might be quite tricky for new developers as documentation states that extending AbstractDataCollector
is the simplest way to register the collector without any extra configuration.
Problem 2
Customizing DataCollector name using getName
and relying on autowire completely causes the template file resolution for the collector to fail. This is because template is registered using service ID (FQCN by default), while collector is added to Profiler
using getName()
result as profiler ID. This requires user to customize the tag definition in services.yaml
:
App\Infrastructure\DataCollector\DataGridDataCollector:
tags:
- name: data_collector
id: 'data_grid'
which kinda kills the purpose of autoconfiguring functionality.
How to reproduce
Add following class (you may inject any existing service in your app) and use autowire: true
:
<?php
namespace App\Infrastructure\DataCollector;
use App\Infrastructure\DataGrid\Debug\DataGridCall;
use App\Infrastructure\DataGrid\Debug\TraceableDataGridHandler;
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
class DataGridDataCollector extends AbstractDataCollector
{
public function __construct(private TraceableDataGridHandler $dataGridHandler)
{
}
public function collect(Request $request, Response $response, Throwable $exception = null): void
{
$this->data['calls'] = $this->dataGridHandler->getCalls();
}
public function reset(): void
{
$this->data = [];
$this->dataGridHandler->clearCalls();
}
public function getCalls(): array
{
return $this->data['calls'] ?? [];
}
public function getName(): string
{
// return self::class;
return 'data_grid';
}
public static function getTemplate(): ?string
{
return 'data_collector/data_grid.html.twig';
}
}
Possible Solution
Problem 1
Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector
should extend Symfony\Component\HttpKernel\DataCollector\DataCollector
(probably breaking change)
Problem 2
🤷🏻♂️