Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Eigene Services erstellen

Eigene Services erstellen

~15 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Zeit, unsere ERSTE eigene Geschäftslogik in einen dedizierten Service auszulagern, statt sie im Controller zu belassen – die Statistik-Berechnung aus Kapitel 24.

Warum Geschäftslogik aus dem Controller gehört

Controller SOLLTEN dünn bleiben: Anfrage entgegennehmen, an die richtige Logik delegieren, Antwort zurückgeben. Komplexere Berechnungen, die MEHRERE Repositories kombinieren oder wiederverwendbar sein sollen (z. B. auch von einem Console Command in Block 7 aus), gehören in einen EIGENEN Service.

Einen Service generieren

php bin/console make:service ProjectStatistikService
src/Service/ProjectStatistikService.php
<?php

declare(strict_types=1);

namespace App\Service;

use App\Entity\Project;
use App\Repository\TaskRepository;

class ProjectStatistikService
{
    public function __construct(
        private readonly TaskRepository $taskRepository,
    ) {
    }

    /**
     * @return array{offen: int, in_arbeit: int, erledigt: int, fortschritt: float}
     */
    public function berechneStatistik(Project $project): array
    {
        $rohStatistik = $this->taskRepository->zaehleAufgabenNachStatus($project);

        $anzahlProStatus = ['offen' => 0, 'in_arbeit' => 0, 'erledigt' => 0];
        foreach ($rohStatistik as $zeile) {
            $anzahlProStatus[$zeile['status']] = $zeile['anzahl'];
        }

        $gesamt = array_sum($anzahlProStatus);
        $fortschritt = $gesamt > 0
            ? round(($anzahlProStatus['erledigt'] / $gesamt) * 100, 1)
            : 0.0;

        return [
            ...$anzahlProStatus,
            'fortschritt' => $fortschritt,
        ];
    }
}

KEINE Attribute, KEINE spezielle Basisklasse nötig – JEDE gewöhnliche PHP-Klasse mit typisierten Constructor-Parametern ist AUTOMATISCH als Service via Autowiring nutzbar (Symfonys "Services sind standardmäßig autowired und autoconfigured"-Konvention aus config/services.yaml, dazu mehr in Kapitel 34).

Den Service im Controller nutzen

use App\Service\ProjectStatistikService;

#[Route('/projects/{id}', name: 'project_show', requirements: ['id' => '\d+'])]
public function show(
    int $id,
    ProjectRepository $projectRepository,
    ProjectStatistikService $statistikService,
): Response {
    $projekt = $projectRepository->find($id);

    if ($projekt === null) {
        throw $this->createNotFoundException();
    }

    $this->denyAccessUnlessGranted(ProjectVoter::VIEW, $projekt);

    return $this->render('project/show.html.twig', [
        'projekt' => $projekt,
        'statistik' => $statistikService->berechneStatistik($projekt),
    ]);
}

GENAU dasselbe Autowiring-Prinzip wie bei LoggerInterface oder ProjectRepository – der Controller weiß NICHT, wie ProjectStatistikService intern funktioniert, nur DASS er berechneStatistik() aufrufen kann.

Services können andere Services nutzen

Autowiring funktioniert GENAUSO zwischen Services – ein Service kann im eigenen Constructor beliebig viele ANDERE Services anfordern, GENAU wie ein Controller. ProjectStatistikService selbst könnte z. B. später einen CacheInterface-Service injiziert bekommen (Kapitel 45), OHNE dass sich der aufrufende Controller-Code ändern müsste.

Faustregel: wann lohnt sich ein eigener Service?

SituationEmpfehlung
Einfache, EINMALIGE Logik in EINER Controller-MethodeDirekt im Controller belassen – ein eigener Service wäre unnötige Indirektion.
Logik, die von MEHREREN Stellen gebraucht wird (Controller UND Console Command UND Event Listener)In einen Service auslagern – EIN Ort für die Wahrheit, statt Code-Duplikation.
Komplexe Berechnung/Orchestrierung MEHRERER RepositoriesIn einen Service auslagern – hält den Controller lesbar und die Logik isoliert testbar (Block 7).

Tipp: Ein guter Namenskonvention-Hinweis: Service-Klassennamen enden oft auf Service, Manager oder beschreiben direkt ihre Aufgabe (z. B. ProjectStatistikBerechner) – WICHTIGER als der exakte Namensstil ist KONSISTENZ innerhalb eines Projekts.