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
<?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.