Services & Dependency Injection

Der Service-Container

Shopware nutzt den Dependency-Injection-Container von Symfony. Eigene Klassen werden als Services registriert und bekommen ihre Abhängigkeiten automatisch hineingereicht – statt sie selbst zu erzeugen.

Einen Service registrieren

Services werden in der Resources/config/services.xml deklariert. Sobald die Datei existiert, wird sie von Shopware automatisch geladen.

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services">
    <services>
        <service id="Swag\Example\Service\PriceFormatter">
            <argument type="service" id="Shopware\Core\System\SystemConfig\SystemConfigService"/>
        </service>
    </services>
</container>

Die Service-Klasse

Die Abhängigkeit kommt über den Konstruktor – klar, testbar und ohne globalen Zustand.

<?php declare(strict_types=1);

namespace Swag\Example\Service;

use Shopware\Core\System\SystemConfig\SystemConfigService;

class PriceFormatter
{
    public function __construct(private readonly SystemConfigService $config)
    {
    }

    public function format(float $value): string
    {
        $decimals = (int) $this->config->get('SwagExample.config.decimals');
        return number_format($value, $decimals, ',', '.') . ' €';
    }
}

Autowiring

Gibt man autowire="true" an, löst Symfony die Konstruktor-Argumente anhand ihrer Typen selbst auf – die explizite <argument>-Zeile entfällt dann meist:

<service id="Swag\Example\Service\PriceFormatter" autowire="true"/>

Faustregel: Fachliche Logik gehört in Services, nicht in Templates oder Controller. So bleibt sie an einer Stelle, testbar und wiederverwendbar.

Services sind die Bausteine. Damit sie zur richtigen Zeit laufen, hängt man sie an Events.