Symfony performance tips
25. 10. 2026Vytváření velkých služeb s mnoha závislostmi přináší řadu výkonových problémů. Za inicializaci a načtení takové služby zaplatíme operační pamětí, početním výkonem i časem odbavení požadavku. Ukážeme si tři základní techniky, jak služby v Symfony optimalizovat a přitom udržet přehledný kód.
1. Rozděl a panuj
Symfony umí službu injektnout rovnou do argumentu metody controlleru. Nevytvářej „god service". Operace rozděl do samostatných micro služeb s jednou zodpovědností. Každá služba pak volá pouze to, co opravdu potřebuje. Jako bonus dostaneš lepší strukturu, přehlednější kód a snadnější refaktorování v budoucnu.
final class ArticleController extends AbstractController
{
#[Route('/article', methods: ['POST'])]
public function create(ArticleCreateService $service): Response
{
// ...
}
#[Route('/article/{id}', methods: ['PUT'])]
public function update(int $id, ArticleUpdateService $service): Response
{
// ...
}
#[Route('/article/{id}', methods: ['DELETE'])]
public function delete(int $id, ArticleDeleteService $service): Response
{
// ...
}
} 2. #[Lazy] — odlož vytvoření služby, dokud ji nepotřebuješ
Někdy službu v konstruktoru mít musíš, ale použiješ ji jen za určitých podmínek. Například ArticleCreateService, který umí zpracovat i ilustrativní obrázek z formuláře — ale jen pokud ho uživatel přiložil. DIC díky atributu #[Lazy] vytvoří proxy na službu a reálnou službu inicializuje až ve chvíli, kdy se na ni v kódu skutečně zeptáme.
use Symfony\Component\DependencyInjection\Attribute\Lazy;
final class ArticleCreateService
{
public function __construct(
#[Lazy]
private readonly ImageUploadService $imageUploader,
) {
}
public function create(ArticleData $data): Article
{
$article = new Article($data->title, $data->content);
if ($data->image !== null) {
// ImageUploadService se instancuje teprve tady
$article->setImagePath(
$this->imageUploader->upload($data->image)
);
}
return $article;
}
} Když článek obrázek nemá, ImageUploadService a jeho závislosti se nikdy nevytvoří.
3. Service locator
Ideální nástroj, pokud například píšeme službu ke zpracování datových zdrojů a potřebujeme zavolat parser podle typu dat.
public function __construct(
#[AutowireLocator([
XmlParserService::class,
DbParserService::class,
MdParserService::class
])]
private readonly ContainerInterface $parsers
) {
} V metodě handle() pak podle typu dat zavoláme potřebný parser.
public function handle(string $payload): array
{
$parserClassName = $this->getParserClassNameByData($payload);
$parser = $this->parsers->get($parserClassName);
return $parser->toArray($payload);
} Tři parsery jsou registrované, ale instancuje se vždy jen ten, který zrovna potřebujeme.
Všechny tři přístupy míří na totéž - neplatit za vytváření služeb, které v daném requestu stejně nepoužiješ.

