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

Filter und Sortierung in der GraphQL-Query anbieten

Filter und Sortierung in der GraphQL-Query anbieten

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

Die events-Query aus Kapitel 13 liefert bisher immer alle aktiven Veranstaltungen in Einfügereihenfolge. Dieses Kapitel ergänzt einen filter- und einen sort-Parameter, beide als eigene Input-Typen (Kapitel 6), die bewusst die vorhandenen Core-Bausteine FilterTypeInput und SortEnum wiederverwenden.

Den Filter-Input-Typ deklarieren

app/code/Mironsoft/Event/etc/schema.graphqls
input EventFilterInput @doc(description: "Identifies which fields to filter events by") {
    title: FilterTypeInput
    location: FilterTypeInput
}

input EventSortInput @doc(description: "Specifies which fields to sort events by") {
    title: SortEnum
    start_at: SortEnum
}

FilterTypeInput ist derselbe Core-Typ, der bereits in Kapitel 3 in der Produktsuche aufgetaucht ist - er bringt Operatoren wie eq, like, in mit, ohne dass das Event-Modul sie neu definieren muss. SortEnum ist ein einfaches Enum mit den Werten ASC und DESC, ebenfalls aus Magento_CatalogGraphQl.

Die Argumente an der Query ergänzen

app/code/Mironsoft/Event/etc/schema.graphqls
type Query {
    events(
        filter: EventFilterInput
        sort: EventSortInput
        pageSize: Int = 20
        currentPage: Int = 1
    ): Events
        @resolver(class: "Mironsoft\\Event\\Model\\Resolver\\Events")
        @doc(description: "Returns a filtered, sorted, paginated list of active events")
}

Den DataProvider erweitern

Die getList()-Signatur aus Kapitel 13 bekommt zwei zusätzliche, optionale Parameter. Beide werden über den bereits vorhandenen SearchCriteriaBuilder in Filter bzw. Sortierreihenfolgen übersetzt:

app/code/Mironsoft/Event/Model/Resolver/DataProvider/Events.php (Auszug, ergänzte getList-Signatur)
/**
 * Fetches active events for the given page, optionally filtered and sorted.
 *
 * @param int $pageSize Number of events per page
 * @param int $currentPage Requested page, 1-based
 * @param array<string, array<string, string>>|null $filter Field => [operator => value]
 * @param array<string, string>|null $sort Field => direction (ASC/DESC)
 * @return array{items: array<int, array<string, mixed>>, total_count: int, page_info: array<string, int>}
 */
public function getList(
    int $pageSize,
    int $currentPage,
    ?array $filter = null,
    ?array $sort = null
): array {
    $this->searchCriteriaBuilder->addFilter(EventInterface::IS_ACTIVE, 1);

    foreach ($filter ?? [] as $field => $operatorValuePairs) {
        foreach ($operatorValuePairs as $operator => $value) {
            $this->searchCriteriaBuilder->addFilter($field, $value, $operator);
        }
    }

    $this->searchCriteriaBuilder->setCurrentPage($currentPage);
    $this->searchCriteriaBuilder->setPageSize($pageSize);
    $searchCriteria = $this->searchCriteriaBuilder->create();

    foreach ($sort ?? [] as $field => $direction) {
        $sortOrder = $this->sortOrderBuilder->setField($field)
            ->setDirection($direction)
            ->create();
        $searchCriteria->setSortOrders([$sortOrder]);
    }

    // ... Rest wie in Kapitel 13: Repository aufrufen, Items mappen, page_info bauen
}

$sortOrderBuilder (\Magento\Framework\Api\SortOrderBuilder) kommt als weitere Konstruktor-Abhängigkeit hinzu - konsequent per Constructor Property Promotion, wie jede andere Abhängigkeit in diesem Projekt.

Den Resolver anpassen

$filter = $args['filter'] ?? null;
$sort = $args['sort'] ?? null;

return $this->eventsDataProvider->getList(
    (int) ($args['pageSize'] ?? 20),
    (int) ($args['currentPage'] ?? 1),
    $filter,
    $sort
);

Die erweiterte Query in der Praxis

query {
  events(
    filter: { location: { eq: "Berlin" } }
    sort: { start_at: ASC }
    pageSize: 10
  ) {
    items { title location start_at }
    total_count
  }
}

Achtung: $args['filter'] kommt aus GraphQL als verschachteltes Array mit dem Operator als Schlüssel (['location' => ['eq' => 'Berlin']]) - praktisch identisch mit dem, was addFieldToFilter() selbst als zweiten Parameter erwartet. Diese strukturelle Ähnlichkeit ist kein Zufall: FilterTypeInput wurde bewusst so modelliert, dass es sich direkt in Magentos Collection-Filter-API übersetzen lässt.

Tipp: Bei mehreren gleichzeitig gesetzten Filterfeldern verknüpft SearchCriteriaBuilder::addFilter() ohne weitere Angaben automatisch per UND - für ODER-Verknüpfungen bräuchte es eine gemeinsame Filtergruppe über addFilters() mit mehreren Filtern im selben Array. Für die meisten Storefront-Filter (wie hier) reicht die einfache UND-Verknüpfung völlig aus.

Kapitel 15 rundet Block 4 ab: eine einzelne Veranstaltung gezielt per Identifier abfragen, statt immer die gesamte (gefilterte) Liste zu laden.