Symfony performance tips

25. 10. 2026

Vytvář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š.

Buy me a coffee icon Support on Patreon

Nejnovější příspěvky