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

Query-Extensions für globale Abfrage-Anpassungen

Query-Extensions für globale Abfrage-Anpassungen

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

Kapitel 55 filterte EINE Collection über einen ERSETZENDEN Provider – Query Extensions bieten eine ELEGANTERE Alternative, die den STANDARD-Provider ERGÄNZT statt zu ersetzen, und AUTOMATISCH auf MEHRERE Resources anwendbar ist.

Das QueryCollectionExtensionInterface

api/src/Doctrine/OwnerFilterExtension.php
<?php

declare(strict_types=1);

namespace App\Doctrine;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Metadata\Operation;
use App\Entity\Project;
use App\Entity\User;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\SecurityBundle\Security;

final class OwnerFilterExtension implements QueryCollectionExtensionInterface
{
    public function __construct(
        private readonly Security $security,
    ) {
    }

    public function applyToCollection(
        QueryBuilder $queryBuilder,
        \ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator,
        string $resourceClass,
        ?Operation $operation = null,
        array $context = [],
    ): void {
        if (Project::class !== $resourceClass) {
            return;
        }

        $user = $this->security->getUser();

        if (!$user instanceof User || \in_array('ROLE_ADMIN', $user->getRoles(), true)) {
            return;
        }

        $alias = $queryBuilder->getRootAliases()[0];
        $queryBuilder
            ->andWhere("{$alias}.owner = :current_user")
            ->setParameter('current_user', $user);
    }
}

GENAU dieselbe Filterlogik wie OwnProjectsCollectionProvider aus Kapitel 55 – ABER: applyToCollection() ERGÄNZT NUR die QueryBuilder-Bedingung, statt die GESAMTE Abfrage zu ÜBERNEHMEN.

Der entscheidende Vorteil

WEIL die Standard-QueryBuilder-Logik ERHALTEN bleibt, funktionieren Pagination, SearchFilter, OrderFilter (Block 4) WEITERHIN VOLLSTÄNDIG – der ERSETZENDE Provider aus Kapitel 55 hatte GENAU DAS als bekannte Einschränkung.

Die Extension registrieren

GENAU wie Voters (Kapitel 52) und Filter (Kapitel 31) wird die Extension AUTOMATISCH über das implementierte Interface erkannt – KEINE manuelle services.yaml-Eintragung nötig, SOLANGE Symfonys Autowiring/Autoconfigure aktiv ist (STANDARD in der api-platform-Distribution).

Den alten Provider entfernen

// Project.php - provider-Parameter aus Kapitel 55 ENTFERNEN
new GetCollection(), // OHNE provider: OwnProjectsCollectionProvider::class

Achtung: Extensions und ERSETZENDE Provider SCHLIESSEN sich GEGENSEITIG aus – EIN ersetzender Provider IGNORIERT Extensions KOMPLETT, da er den STANDARD-Mechanismus GAR NICHT erst aufruft. Kapitel 55 diente dem SCHRITTWEISEN Verständnis, Extensions sind die AUSGEREIFTERE Lösung für DIESEN Anwendungsfall.

QueryItemExtensionInterface für Einzelobjekte

ANALOG existiert QueryItemExtensionInterface mit applyToItem() für GET /api/projects/{id} – NÜTZLICH, um DIESELBE Sichtbarkeitsregel AUCH auf Einzelabrufe anzuwenden, statt sich AUSSCHLIESSLICH auf den Voter (Kapitel 53) zu verlassen.

Tipp: Query Extensions sind der PROFESSIONELLE Standardweg für GLOBALE, wiederkehrende Datenbank-Filterlogik in API Platform – EMPFEHLENSWERT GEGENÜBER ersetzenden Providern, WANN IMMER die Standard-Doctrine-Query WEITERHIN sinnvoll bleibt.