Warum werden Routing-Dateien mit Unterstrichen gefüllt?

24

Wie verhält es sich mit allen Parametern mit und ohne vorangestelltem Unterstrich ?

Wo entscheidet Drupal, wie diese Parameter verarbeitet werden?

Wurde dieses Konzept von Symfony eingeführt oder ist es für Drupal neu?

Beispiel ( node.routing.yml ):

node.overview_types:
  path: '/admin/structure/types'
  defaults:
    _controller: '\Drupal\Core\Entity\Controller\EntityListController::listing'
    entity_type: 'node_type'
    _title: 'Content types'
  requirements:
    _permission: 'administer content types'
Daniel
quelle
2
Es ist eine Symfony-Convention . Es gibt einen guten Artikel hier , finden Sie das Bit, das sagt. Das letzte, was Sie beachten müssen, ist die spezielle Bedeutung des Unterstrichs in den Parameternamen. Parameter, die mit diesem Zeichen beginnen, haben eine besondere Bedeutung
Clive
1
Vielen Dank, Clive. Dieser Artikel erwähnt "besondere Bedeutung", erklärt dies jedoch überhaupt nicht. Warum können nicht unterstrichene Parameter auch etwas Besonderes sein?
Daniel
1
lol, warum können Nicht-Unterstrich-Parameter auch etwas Besonderes sein? , das klingt nach einer zutiefst existenziellen Frage! Normalerweise (nur normalerweise) werden Präfixvariablen verwendet, um entweder eine "private" Variable anzugeben (hier unwahrscheinlich) oder um Kollisionen mit anderen Klassen / Methoden / etwas anderem in einem System zu vermeiden. Wäre gut, die offiziellen Dokumente zu sehen, ja
Clive

Antworten:

41

Hier finden Sie eine hoffentlich gute Erklärung für die Idee des Routingsystems sowie für die Drupal-spezifischen Ergänzungen.

Gesamtübersicht

Die Symfony-Komponenten haben hier zwei wichtige Konzepte. Der http-Kernel ist ein System, das die Anforderung erhält und andere Systeme auffordert, den Code zu definieren, der die angeforderte Ausgabe (ein Antwortobjekt) erzeugt, und die Antwort an den Client zurückzusenden. Dieser Code heißt controller. Dies kann entweder eine reine PHP4-ähnliche Funktion, eine Methode für ein Objekt oder sogar eine anonyme Funktion sein.

Das System, das weiß, welcher Controller für die aktuelle Anforderung verantwortlich ist, ist das Routingsystem.

Bildbeschreibung hier eingeben

Grundlegende Routing-Datei

Als Modulentwickler definieren Sie die Routenliste und die entsprechenden Controller.

Hier ist ein Beispiel für eine JSON-Antwort:

taxonomy.autocomplete_vid:
  path: '/taxonomy/autocomplete_vid/{taxonomy_vocabulary}'
  defaults:
    _controller: '\Drupal\taxonomy\Controller\TermAutocompleteController::autocompletePerVid'
  requirements:
    taxonomy_vocabulary: \d+

Die meisten Symfony-Dokumente erwähnen Pattern, aber Drupal hat beschlossen, nur den nicht veralteten "Pfad" -Schlüssel in seiner Routing-Datei zuzulassen.

Das Schlüsselkonzept ist die Steuerung, die einige Parameter aus dem System abruft und diese in die Antwort umwandelt. In diesem Beispiel haben Sie den Parameter 'taxonomy_vocabulary'. Alles ohne Unterstrich wird also als Parameter für die Steuerung angesehen. Wenn Sie einen Standardwert angeben möchten, geben Sie ihn in das Standardarray ein. Im selben yml-Array geben Sie die Klasse und die Methode an, die mit '::' verbunden sind, um dem System mitzuteilen, wo Dinge nachgeschlagen werden sollen. Jede andere Eigenschaft hat nichts mit den Reglerparametern zu tun und wird daher als intern betrachtet und hat einen Unterstrich als Präfix.

Mit Symfony selbst können Sie auch reguläre Ausdrücke definieren, um zu überprüfen, ob der eingehende Parameter gültig ist (mithilfe von "Anforderungen"). Hier würde es nur zu Zahlen passen.

Controller Resolver

Sobald symfony herausgefunden hat, welcher Controller für die aktuelle Anforderung aktiv ist, fordert es den sogenannten Controller-Resolver auf, eine Instanz des Controllers zu erstellen, die über call_user_func_array ausgeführt werden kann. Der Controller-Resolver verfügt über eine Methode zum Aufrufen des Controllers (Objekt + Methode, anonyme Funktion) und eine Methode zum Übergeben der Parameter an den Controller (siehe Controller-Resolver)

Drupal-Erweiterungen

Dies ist im Grunde, was Symfony Ihnen gibt.

Drupal ist allerdings etwas komplizierter:

  • Sie können den Zugriff auf die Route überprüfen. Zum Beispiel war das Aufrufen von user_access () in Drupal 7 und darunter sehr verbreitet.
  • Sie möchten das taxonomy_vocabulary nicht in sein tatsächliches Entitätsobjekt konvertieren
  • Sie möchten nicht die vollständige Seitenantwort generieren, sondern nur den "Hauptinhalt".

Zugangskontrolle

Drupal hat zusätzlich zu den Symfony-Teilen ein System eingeführt, das prüft, ob der Benutzer Zugriff auf die aktuelle Route hat, und alternativ eine 403-Ausnahme (Zugriff verweigert) auslöst. Zugriffsmanager

In der Routing-Datei geben Sie dies im Anforderungsteil an. Die am häufigsten verwendeten Bits sind im folgenden Beispiel aufgeführt:

  path: '/user/{user}'
  options:
    _access_mode: 'ANY'
  requirements:
    _permission: 'access user profiles'
    _entity_access: 'user.view'
    _role: 'administrator'

_permission definiert einen Aufruf von user_access (), _role stellt sicher, dass der Benutzer eine bestimmte Rolle hat (Sie können mehrere über, für OR und + für AND-Logik angeben). _entity_access fragt das Entitätssystem, ob Sie Zugriff zum Anzeigen der Benutzerentität haben. Standardmäßig stellt Drupal sicher, dass Sie Zugriffsprüfer hinzufügen, mit denen Sie fortfahren können. Sie können dies jedoch in den Optionen über den _access_mode ändern.

Upcasting

Wie in der Auflistung erwähnt, möchten Sie sich nicht darum kümmern, eine Entität zu laden, siehe / user / {user} als Beispiel. Für Entitäten verwenden Sie im Grunde nur den Namen des Entitätstyps und es wird ein entity_load mit der in der URL übergebenen ID ausgeführt. Param Converter Manager

Seitenantwort

Wie zuvor beschrieben, ist der Controller dafür verantwortlich, das Antwortobjekt zu generieren. Dies wäre in Drupal schrecklich, da eine Seite so viel mehr wie alle Blöcke in ihren Regionen, die HTML- und Seitenvorlagen usw. enthält. Daher hat Drupal einen anderen Schlüssel angegeben, um einen Controller anzugeben, der den Inhalt einer Seite zurückgibt:

user.page:
  path: '/user'
  defaults:
    _content: '\Drupal\user\Controller\UserController::userPage'
  requirements:
    _access: 'TRUE'

Die definierte Zeichenfolge ist der Controller, der zum Generieren des Render-Arrays für den Hauptinhaltsbereich Ihrer Seite verwendet wird.

Eine weitere Ergänzung ist der Umgang mit Formularen, da das Zurückgeben einer Seite mit einem Formular etwas komplexer ist als nur ein Render-Array, sodass Sie _form mit dem FormInterface definieren können, das für das aktuelle Formular verantwortlich ist.

user.pass:
  path: '/user/password'
  defaults:
    _form: '\Drupal\user\Form\UserPasswordForm'
  requirements:
    _access: 'TRUE'

Hinweis: Dies deckt die wichtigsten Punkte aus meiner Sicht ab, obwohl es mit Sicherheit noch viel mehr Punkte zu besprechen gibt.

TL; DR

  • Unterstriche werden für alles angegeben, was für die Steuerung keine Parameter sind. Dies ist eine Art "Standard" von Symfony.
  • Diese Parameter werden über den Parameterkonverter übertragen und mit dem Controller Resolver an den Controller übergeben
  • Drupal enthält einige Ergänzungen, die es den Benutzern erleichtern sollen, mit dem symfony-Routingsystem zu interagieren.
Daniel Wehner
quelle
Wow. Beeindruckende Antwort. Warum sind in bestimmten Parametern Punkte enthalten, die sich von der Verwendung eines Unterstrichs unterscheiden? Eg user.pass(im Beispiel oben) gegenüber user_pass. Ist das auch eine Symfony-Convention?
Chrisjlee
2
Es gibt eine Art Konvention, um $ module. $ Name als Maschinennamen einer Route zu verwenden. Nichts davon geht jedoch von innen aus.
Daniel Wehner
Gemäß dem folgenden Problem wird _content überhaupt nicht mehr verwendet, _controller jedoch. Das Beispiel im Teil " Seitenantwort" ist daher nicht aktuell. drupal.org/node/2378809 Wenn wir Daten im Inhaltsbereich unserer Seite anzeigen möchten, definiert der Controller ein Render-Array, ähnlich wie in Drupal 7. Wenn wir das umgehen und unsere Seite erstellen möchten von Grund auf neu, dann können wir ein Response-Objekt zurückgeben.
Benelori
Na klar, man kann nicht erwarten, dass 1,5 Jahre nicht passieren
Daniel Wehner