logo

Extra Block Types (EBT) - Neue Erfahrung im Layout Builder❗

Extra Block Types (EBT) - gestylte, anpassbare Blocktypen: Diashows, Registerkarten, Karten, Akkordeons und viele andere. Eingebaute Einstellungen für Hintergrund, DOM Box, Javascript Plugins. Erleben Sie die Zukunft der Layouterstellung schon heute.

Demo EBT-Module EBT-Module herunterladen

❗Extra Absatztypen (EPT) - Erfahrung mit neuen Absätzen

Extra Paragraph Types (EPT) - analoger, auf Absätzen basierender Satz von Modulen.

Demo EPT-Module EPT-Module herunterladen

Scroll
22/05/2025, by Ivan
```html

Sammlungen sind Auflistungen von Ressourcen. In einer entkoppelten Website werden sie verwendet, um Dinge wie eine "Neue Inhalte"-Liste oder einen "Meine Inhalte"-Bereich auf der Client-Seite zu erstellen.

Wenn Sie jedoch eine ungefilterte Anfrage an einen Collection-Endpunkt wie /jsonapi/node/article stellen, erhalten Sie einfach alle Artikel, die Sie sehen dürfen.

Ohne Filter können Sie nicht nur Ihre Artikel oder nur Artikel über Lamas abrufen.

Dieser Leitfaden zeigt Ihnen, wie Sie Filter wie ein Profi erstellen.

Schnellstart

Der einfachste und häufigste Filter ist ein Key-Value-Filter:

?filter[field_name]=value&filter[field_other]=value

Dies entspricht allen Ressourcen, bei denen "field_name" gleich "value" und "field_other" gleich "value" ist.

Für alles andere lesen Sie weiter!

Zusammenfassung


Das JSON:API-Modul verfügt über einige der leistungsfähigsten und funktionsreichsten Filterfunktionen überhaupt. All diese Power bringt allerdings eine gewisse Lernkurve mit sich.

Am Ende dieses Artikels werden Sie in der Lage sein, komplexe Abfragen zu erstellen und Probleme zu durchdenken, wie: „Wie bekomme ich eine Liste der Artikel eines Autors über Lamas oder das schnellste Tier der Welt, den Wanderfalken?“

Wir fangen bei den Grundlagen an. Danach zeigen wir Ihnen einige Abkürzungen, mit denen Sie Filter schneller und weniger umständlich schreiben können. Schließlich sehen wir uns eine Reihe von Filterbeispielen aus der Praxis an.

Wenn Sie kein Neuling in Drupal sind, haben Sie wahrscheinlich schon das Views-Modul für diese Aufgaben verwendet. Im Gegensatz zum REST-Modul aus dem Drupal-Core exportiert JSON:API keine Views-Ergebnisse. Sammlungen sind der API-First-Ersatz von JSON:API für exportierte „REST-Displays“ in Views.

Filter erstellen


Die grundlegenden Bausteine von JSON:API-Filtern sind Bedingungen und Gruppen. Bedingungen legen fest, dass etwas zutrifft, und Gruppen erlauben Ihnen, diese Aussagen zu logischen Mengen zusammenzufassen, um größere Bedingungsgruppen zu bilden. Diese Mengen können geschachtelt werden, um sehr feine Abfragen zu erstellen. Sie können sich diese verschachtelten Mengen wie einen Baum vorstellen:

Konventionelle Darstellung:

a( b() && c( d() || e() ) )

Baum-Darstellung:

   a
  / \
 b & c
    / \
   d | e

In beiden Darstellungen:

„d“ und „e“ sind Mitglieder von „c“ in einer ODER-Gruppe.
„b“ und „c“ sind Mitglieder von „a“ in einer UND-Gruppe.

Was ist nun in einer Bedingung enthalten?

Lassen Sie uns logisch werden 🖖. Denken Sie daran, eine Bedingung sagt Ihnen etwas WAHRES oder FALSCHES über eine Ressource und eine Behauptung, die Sie darüber treffen, z. B. „Wurde diese Entität von einem bestimmten Benutzer erstellt?“ Wenn die Bedingung für eine Ressource FALSCH ist, wird diese Ressource nicht in die Sammlung aufgenommen.

Eine Bedingung hat 3 Hauptbestandteile: einen Pfad, einen Operator und einen Wert.

  • Ein „Pfad“ identifiziert ein Feld auf einer Ressource
  • Ein „Operator“ ist eine Vergleichsmethode
  • Ein „Wert“ ist das, woran Sie vergleichen

Im Pseudocode sieht eine Bedingung so aus:

($field !== 'space')

Wo:

  1. $field ist das Feld der Ressource, das durch den „Pfad“ identifiziert wird
  2. der „Operator“ ist !==
  3. der „Wert“ ist der String 'space'

Im JSON:API-Modul können wir das nicht ganz so hübsch aussehen lassen, weil es in einen URL-Query-String passen muss. Dafür repräsentieren wir jede Bedingung mit Schlüssel/Wert-Paaren.

Wenn wir nach dem Vornamen eines Benutzers filtern, könnte eine Bedingung so aussehen:

?filter[a-label][condition][path]=field_first_name
&filter[a-label][condition][operator]=%3D  <- kodiertes "=" Symbol
&filter[a-label][condition][value]=Janis

Beachten Sie, dass wir im ersten eckigen Klammerpaar ein Label verwenden. Wir hätten auch b-label oder this_is_my_super_awesome_label oder sogar eine Zahl wie 666 🤘😅 verwenden können. Der Punkt ist: Jede Bedingung oder Gruppe sollte einen Bezeichner haben.

Aber was, wenn wir viele Janises im System haben?

Fügen wir einen weiteren Filter hinzu, damit wir nur Janises mit einem Nachnamen bekommen, der mit „J“ beginnt:

?filter[first-name-filter][condition][path]=field_first_name
&filter[first-name-filter][condition][operator]=%3D  <- kodiertes "="
&filter[first-name-filter][condition][value]=Janis

&filter[last-name-filter][condition][path]=field_last_name
&filter[last-name-filter][condition][operator]=STARTS_WITH
&filter[last-name-filter][condition][value]=J

Vielleicht ist der Plural von Janis „Janii“ 🤔...

Es gibt viele weitere Filteroperatoren als nur = und STARTS_WITH. Hier ist die vollständige Liste direkt aus dem JSON:API-Code:

\Drupal\jsonapi\Query\EntityCondition::$allowedOperators = [
  '=', '<>',
  '>', '>=', '<', '<=',
  'STARTS_WITH', 'CONTAINS', 'ENDS_WITH',
  'IN', 'NOT IN',
  'BETWEEN', 'NOT BETWEEN',
  'IS NULL', 'IS NOT NULL',
];

Symbol-Operatoren müssen url-codiert werden. Sie erhalten die korrekte Kodierung mit der PHP-Funktion urlencode().

Bedingungsgruppen


Jetzt wissen wir, wie man Bedingungen erstellt, aber noch nicht, wie man Bedingungsgruppen baut. Wie erstellen wir also einen Baum wie oben gezeigt?

Dafür brauchen wir eine „Gruppe“. Eine Gruppe ist eine Menge von Bedingungen, die durch eine „Konjunktion“ verknüpft sind. Alle Gruppen haben Konjunktionen und eine Konjunktion ist entweder UND oder ODER.

Jetzt ist unser Filter ein wenig zu spezifisch! Angenommen, wir wollen alle Benutzer finden, deren Nachname mit „J“ beginnt und die entweder den Vornamen „Janis“ oder den Vornamen „Joan“ haben.

Dafür fügen wir eine Gruppe hinzu:

?filter[rock-group][group][conjunction]=OR

Dann müssen wir unsere Filter dieser neuen Gruppe zuweisen.

Dafür fügen wir einen memberOf-Schlüssel hinzu. Jede Bedingung und Gruppe kann einen memberOf-Schlüssel haben.

Tipp: Gruppen können genauso wie Bedingungen einen memberOf-Schlüssel haben, was bedeutet, dass wir Gruppen von Gruppen haben können 🤯!

Hinweis: Jeder Filter ohne einen memberOf-Schlüssel wird als Teil einer „Root“-Gruppe mit einer UND-Konjugation angenommen.

Alles zusammengefügt sieht das so aus:

?filter[rock-group][group][conjunction]=OR

&filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][operator]=%3D
&filter[janis-filter][condition][value]=Janis
&filter[janis-filter][condition][memberOf]=rock-group

&filter[joan-filter][condition][path]=field_first_name
&filter[joan-filter][condition][operator]=%3D
&filter[joan-filter][condition][value]=Joan
&filter[joan-filter][condition][memberOf]=rock-group

&filter[last-name-filter][condition][path]=field_last_name
&filter[last-name-filter][condition][operator]=STARTS_WITH
&filter[last-name-filter][condition][value]=J

Kommt Ihnen das bekannt vor?

Sollte es, denn wir haben es oben als Baum gesehen:

   a   a = root-and-group
  / \
 /   \    b = last-name-filter
b     c   c = rock-group
     / \
    /   \    d = janis-filter
   d     e   e = joan-filter

Sie können diese Gruppen beliebig tief verschachteln.

Pfade

Bedingungen haben eine letzte Besonderheit: „Pfade“

Pfade bieten eine Möglichkeit, nach Beziehungswerten zu filtern.

Bisher haben wir nur nach den hypothetischen Feldern field_first_name und field_last_name der Benutzerressource gefiltert.

Nehmen wir an, wir möchten nach dem Namen der Karriere eines Benutzers filtern, wobei die Karrieretypen als separate Ressource gespeichert werden. Wir könnten einen Filter wie diesen hinzufügen:

?filter[career][condition][path]=field_career.name
&filter[career][condition][operator]=%3D
&filter[career][condition][value]=Rockstar

Pfade verwenden eine „Dot-Notation“, um Beziehungen zu durchlaufen.

Wenn eine Ressource eine Beziehung hat, können Sie dagegen filtern, indem Sie den Namen des Beziehungsfeldes und den Namen des Beziehungsfeldes mit einem . (Punkt) verbinden.

Sie können sogar nach Beziehungen von Beziehungen (und so weiter) filtern, indem Sie einfach weitere Feldnamen und Punkte hinzufügen.

Tipp: Sie können auf einen bestimmten Index einer Beziehung filtern, indem Sie eine nicht-negative Ganzzahl in den Pfad setzen. Der Pfad some_relationship.1.some_attribute würde beispielsweise nur nach der zweiten zugehörigen Ressource filtern.

Tipp: Sie können nach Untereigenschaften eines Feldes filtern. Zum Beispiel funktioniert ein Pfad wie field_phone.country_code, auch wenn field_phone keine Beziehung ist.

Tipp: Beim Filtern gegen Konfigurationseigenschaften können Sie einen Stern (*) als Platzhalter für einen Teil eines Pfades verwenden. Beispiel: /jsonapi/field_config/field_config?filter[dependencies.config.*]=comment.type.comment würde alle Feldkonfigurationen finden, bei denen ["attributes"]["dependencies"]["config"] (ein indiziertes Array) den Wert "comment.type.comment" enthält.

Abkürzungen


Das sind viele Zeichen zum Tippen. Die meiste Zeit brauchen Sie keine so komplizierten Filter und für diese Fälle bietet das JSON:API-Modul einige „Abkürzungen“, mit denen Sie Filter schneller schreiben können.

Wenn der Operator = ist, müssen Sie ihn nicht angeben. Es wird einfach angenommen. Also:

?filter[a-label][condition][path]=field_first_name
&filter[a-label][condition][operator]=%3D  <- kodiertes "=" Symbol
&filter[a-label][condition][value]=Janis

wird zu

?filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][value]=Janis

Es ist auch selten nötig, nach demselben Feld zweimal zu filtern (obwohl es möglich ist). Wenn der Operator = ist und Sie nicht zweimal nach demselben Feld filtern müssen, kann der Pfad der Bezeichner sein. Also:

?filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][value]=Janis

wird zu

?filter[field_first_name][value]=Janis

Das zusätzliche value ist lästig. Deshalb können Sie die einfachsten Gleichheitsprüfungen auf eine Key-Value-Form reduzieren:

?filter[field_first_name]=Janis

Filter und Zugriffskontrolle


Erst eine Warnung: Verwechseln Sie Filter nicht mit Zugriffskontrolle. Nur weil Sie einen Filter geschrieben haben, der etwas entfernt, das ein Benutzer nicht sehen sollte, heißt das nicht, dass es nicht zugänglich ist. Führen Sie immer Zugriffskontrollen im Backend durch.

Mit diesem wichtigen Hinweis: Sprechen wir darüber, Filter zur Ergänzung der Zugriffskontrolle zu nutzen. Um die Performance zu verbessern, sollten Sie herausfiltern, was Ihre Benutzer nicht sehen können. Die häufigste Supportanfrage im JSON:API-Issue-Queue kann mit diesem einfachen Trick gelöst werden!

Wenn Sie wissen, dass Ihre Benutzer unveröffentlichte Inhalte nicht sehen können, fügen Sie folgenden Filter hinzu:

?filter[status][value]=1

Mit dieser Methode reduzieren Sie die Anzahl unnötiger Anfragen, die Sie machen müssen. Das liegt daran, dass JSON:API keine Daten für Ressourcen zurückgibt, auf die ein Benutzer keinen Zugriff hat. Sie können sehen, welche Ressourcen davon betroffen sind, indem Sie den Bereich meta.errors im JSON:API-Dokument inspizieren.

Tun Sie Ihr Bestes, um nicht zugängliche Ressourcen im Voraus herauszufiltern.

Filter-Beispiele


1. Nur veröffentlichte Nodes abrufen

Ein sehr häufiges Szenario ist das Laden nur der veröffentlichten Nodes. Das ist sehr einfach zu filtern.

KURZ
filter[status][value]=1

NORMAL
filter[status-filter][condition][path]=status
filter[status-filter][condition][value]=1

2. Nodes nach Wert einer Entitätsreferenz filtern

Eine übliche Strategie ist das Filtern von Inhalten anhand einer Entitätsreferenz.

KURZ
filter[uid.id][value]=BB09E2CD-9487-44BC-B219-3DC03D6820CD

NORMAL
filter[author-filter][condition][path]=uid.id
filter[author-filter][condition][value]=BB09E2CD-9487-44BC-B219-3DC03D6820CD

Um vollständig mit der JSON API-Spezifikation konform zu sein: Während Drupal intern die Eigenschaft uuid verwendet, verwendet JSON API id stattdessen.

Seit Drupal 9.3 ist es möglich, auch nach target_id zu filtern und nicht nur nach der uuid-Eigenschaft.

KURZ
filter[field_tags.meta.drupal_internal__target_id]=1

NORMAL
filter[name-filter][condition][path]=field_tags.meta.drupal_internal__target_id
filter[name-filter][condition][value]=1

3. Verschachtelte Filter: Nodes, die von User „admin“ erstellt wurden

Es ist möglich, nach Feldern von referenzierten Entitäten wie Usern, Taxonomie-Feldern oder anderen Entitätsreferenzfeldern zu filtern. Das können Sie einfach tun, indem Sie die folgende Notation verwenden: reference_field.nested_field. In diesem Beispiel ist das Referenzfeld uid für den Benutzer und name ist ein Feld der Benutzer-Entität.

KURZ
filter[uid.name][value]=admin

NORMAL
filter[name-filter][condition][path]=uid.name
filter[name-filter][condition][value]=admin