Routi: Web Routing

Hallo,

ich bastle mir gerade ein kleines Web-Framework. Oberstes Prinzip soll "Konvention über Konfiguration" sein.

ein kleines Beispiel:
http://example.com/modulename/action/optionalvalue

in htaccess:
RewriteRule ^([^/.]+)/([^/.]+)/$ /main-controller.php?module=$1&action=$2
RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)$ /main-controller.php?module=$1&action=$2&value=$3

Modulename ist also das Modul (ein Verzeichnis mit etnsprechender Klassenlogik), action ist der entsprechende Kontroller (z.b. edit oder update).

nochmals drei Linkbeispiele
http://example.com/bildergalerie/show/1224
=> lädt Bildergalerie 1224 via Http-Methode GET

http://example.com/bildergalerie/update/22
=> macht ein Update via POST auf Galerie 22

http://example.com/bildergalerie/showall
=> lädt alle Bildergalerien

Ich denke, man kann sich das soweit vorstellen. ist ja jetzt nichts neues.
Mein Problem ist ein bisschen das Routing. Ich möchte nämlich die Möglichkeit schaffen, Sub-Module zu integrieren. Physikalisch sind das ganz simpel nur Unterverzeichnisse, um eine bessere Organisationsstruktur zu haben.

http://example.com/bildergalerie/thumbnailgalerie/update/22
=> macht ein Update via POST auf Thumbnail-Galerie 22

http://example.com/bildergalerie/thumbnailgalerie/showall
=> lädt alle Thumbnailgalerien

Problem:
in der htaccess-Datei kann ich nun schlecht matchen, was was genau ist...
Folgende Links zum Beispiel werden vom selben Pattern gematched:

bildergalerie/thumbnailgalerie/showall
bildergalerie/update/1224

^([^/.]+)/([^/.]+)/([^/.]+)$

Lösung:
muss ich nach einer Zahl (ID) matchen? Oder wie macht man das am besten? Was ist, wenn Value keine Zahl ist, sondern ein String?

Fragen über Fragen... wie also macht man sinnvolles Routing, ohne Konfiguration?

  1. Tach!

    [...] Web-Framework. Oberstes Prinzip soll "Konvention über Konfiguration" sein.
    http://example.com/modulename/action/optionalvalue
    in htaccess:
    RewriteRule ^([^/.]+)/([^/.]+)/$ /main-controller.php?module=$1&action=$2
    RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)$ /main-controller.php?module=$1&action=$2&value=$3

    Und damit hast du eine feststehende Gegebenheit, die sich nur im Rahmen der Rewrite-Möglichkeiten und -Konfiguration verwenden lässt. Wann immer andere Anforderungen auf einfacherem Weg ohne die starre Struktur zu implementieren sind, muss auch die .htaccess geändert werden. Das lässt sich dort abkürzen, indem nur generell (.*) umgeschrieben wird und dein Router im PHP-Code die URL auseinandernimmt, um dann dort mit sämtlichen Möglichkeiten PHPs den Request auswerten zu können, und nicht nur drei $_GET-Parameter zu haben. Außerdem bleibt so der Querystring unverändert und kann für solche Dinge wie ?sortby=name&sortdir=desc verwendet werden.

    Mein Problem ist ein bisschen das Routing. Ich möchte nämlich die Möglichkeit schaffen, Sub-Module zu integrieren. Physikalisch sind das ganz simpel nur Unterverzeichnisse, um eine bessere Organisationsstruktur zu haben.
    in der htaccess-Datei kann ich nun schlecht matchen, was was genau ist...

    Deswegen in PHP routen.

    dedlfix.

    1. Hi Dedlfix,

      danke für deine Antwort. Ok, werde ich so machen. Trotzdem noch eine Frage:

      wenn ich jetzt so eine URL habe:
      example.com/module1/submodule1/edit/323

      weiß ich ja erstmal nicht, was modulname, was action und was Wert ist. Wie macht man sowas am geschickstesten? Prüfen, ob ein Kontroller (= Methode) existiert?

      Vielleicht mal ganz grundsätzlich, dass ich nicht völlig falsch und umständlich in eine Richtung entwickel... vielen Dank!

      1. Hi

        danke für deine Antwort. Ok, werde ich so machen. Trotzdem noch eine Frage:

        wenn ich jetzt so eine URL habe:
        example.com/module1/submodule1/edit/323

        weiß ich ja erstmal nicht, was modulname, was action und was Wert ist. Wie macht man sowas am geschickstesten? Prüfen, ob ein Kontroller (= Methode) existiert?

        Vielleicht mal ganz grundsätzlich, dass ich nicht völlig falsch und umständlich in eine Richtung entwickel... vielen Dank!

        Da dein ansatz dem von rails sehr ähnlich ist hilft es dir vielleicht dazu ein wenig zu lesen. Rails routing.

        /entropie

        --
        Whenever people agree with me I always feel I must be wrong.
          -- Oscar Wilde
      2. Tach!

        wenn ich jetzt so eine URL habe: example.com/module1/submodule1/edit/323
        weiß ich ja erstmal nicht, was modulname, was action und was Wert ist. Wie macht man sowas am geschickstesten? Prüfen, ob ein Kontroller (= Methode) existiert?

        Du kannst per Konvention festlegen, dass zum Beispiel die Argumente für Modul, Controller, Action und eine optionale beliebige Anzahl an Parametern stehen. Dieses Muster greift immer am Schluss. Davor versuchst du mit konkreten Regeln die Sonderfälle herauszufischen.

        dedlfix.

  2. hi,

    Mein Problem ist ein bisschen das Routing. Ich möchte nämlich die Möglichkeit schaffen, Sub-Module zu integrieren. Physikalisch sind das ganz simpel nur Unterverzeichnisse, um eine bessere Organisationsstruktur zu haben.

    Betrachte die Pfad-Angabe in einem URL als Routing-Information
      http://example.org/model/class/subclass/ressource.html

    Fragen über Fragen... wie also macht man sinnvolles Routing, ohne Konfiguration?

    Ohne Konfiguration macht ein solches 'Routing-Protokoll' nur dann einen Sinn, wenn keine Konfiguration (für etwaige weitere Informationen zu einer Webressource) gebraucht wird. D.h., der Request wird zur Modellklasse geroutet und das ist schon alles.

    In Fakto wird eine 'ressource.html' jedoch ein paar Informationen brauchen, wie z.B. einen Titel, eine Beschreibung und in Hinblick auf HTML5: Mikrodaten.

    Es ergibt sich ein Katze-Schwanz-Problem, weil dazu eine Konfiguration gebraucht wird ;)

    Hotti

    1. Hi,

      Ohne Konfiguration macht ein solches 'Routing-Protokoll' nur dann einen Sinn, wenn keine Konfiguration (für etwaige weitere Informationen zu einer Webressource) gebraucht wird. D.h., der Request wird zur Modellklasse geroutet und das ist schon alles.

      In Fakto wird eine 'ressource.html' jedoch ein paar Informationen brauchen, wie z.B. einen Titel, eine Beschreibung und in Hinblick auf HTML5: Mikrodaten.

      Dokumententitel meinst du? Was hat der Dokumententitel bzw. Meta-Beschreibungen und Mikrodaten in der Routing-Konfiguration zu suchen? Das wird doch alles dynamisch vom Kontroller geladen. So zumindest z.b. bei Django und anderen Webframeworks, mit denen ich so zu tun hatte.

      Aber stimmt schon, an sich ist eine Konfiguration doch nicht ganz unsinnig. Mal sehn

      1. hi,

        Dokumententitel meinst du? Was hat der Dokumententitel bzw. Meta-Beschreibungen und Mikrodaten in der Routing-Konfiguration zu suchen?

        Gar nichts. Auf den ersten Blick zumindest. Wenn die Route automatisch bestimmt wird, muss dann eben der Kontroller in die Konfiguration schauen, was da steht zu 'ressource.html' an weiteren Informationen oder Mikrodaten. Das ist das Katze-Schwanz-Problem: Warum nicht gleich die Konfiguration in die Routing-Table schreiben?

        Das wird doch alles dynamisch vom Kontroller geladen. So zumindest z.b. bei Django und anderen Webframeworks, mit denen ich so zu tun hatte.

        Soso. Wolltest Du nicht was Eigenes bauen?

        Aber stimmt schon, an sich ist eine Konfiguration doch nicht ganz unsinnig. Mal sehn

        Den Plan mit der automatischen Route habe ich schon vor Jahren verworfen ;)

        Hotti

        1. Tach!

          Warum nicht gleich die Konfiguration in die Routing-Table schreiben?

          Weil sie dort nichts zu suchen hat. Separation of Concerns nennt man das. Das Routing routet und macht nichts anderes, dann bleibt es auch schön übersichtlich.

          Das wird doch alles dynamisch vom Kontroller geladen. So zumindest z.b. bei Django und anderen Webframeworks, mit denen ich so zu tun hatte.
          Soso. Wolltest Du nicht was Eigenes bauen?

          Das heißt nicht, dass man alles inklusive der Begrifflichkeiten neu erfinden und bewährte Entwurfsmuster ignorieren muss.

          Aber stimmt schon, an sich ist eine Konfiguration doch nicht ganz unsinnig. Mal sehn
          Den Plan mit der automatischen Route habe ich schon vor Jahren verworfen ;)

          Dann wirst du wohl einen Grund dafür gehabt haben.

          dedlfix.

  3. hi,

    es gibt 2 Möglichkeiten:
    1: Die Route zum Code wird im URL konfiguriert,
    2: Die Route ist statisch in eine Tabelle geschrieben.

    1. Ist wohl das, was Dir vorschwebt.

    1a) Betrachte das mal aus der Sicht der Sicherheit, URLs sind manipulierbar. D.h., ein unberechtigter Request greift auf Deinen Code, der sich dann um die Berechtigungen kümmern muss, spätestens hier wird eine Konfiguration benötigt.

    1b) Parameter im URL: Sofern Parameter das Routing bestimmen, stehen diese Parameter nicht für die Anwendung zur Verfügung. Die Entwicklung von Anwendungen wird eingeschränkt und es ergeben sich unnötig komplizierte Abhängigkeiten. Im einfachsten Fall darf ein Entwickler keine Parameter festlegen oder verwenden, die für das Routing reserviert sind.

    Die genannten Nachteile sind vermeidbar, wenn Du mit statischen Routen (2) arbeitest und selbstverständlich kannst Du auch hier die Routing-Tabelle von der Konfiguration trennen. Der Schlüssel ist in beiden Fällen der URL, der ist eindeutig.

    Hotti

    1. Tach!

      es gibt 2 Möglichkeiten:
      1: Die Route zum Code wird im URL konfiguriert,

      Du meinst, aus der Auswertung der URL ergibt sich 1:1 der auszuführende Programmteil?

      1a) Betrachte das mal aus der Sicht der Sicherheit, URLs sind manipulierbar. D.h., ein unberechtigter Request greift auf Deinen Code, der sich dann um die Berechtigungen kümmern muss, spätestens hier wird eine Konfiguration benötigt.

      Selbst bei Wald- und Wiesen-PHP hat man dieses Problem zu lösen, wenn es Dateien gibt, die nicht direkt (oder nur von bestimmten Nutzern) aufrufbar sein sollen.

      Abgesehen von Berechtigungen fachlicher Natur - wenn ungewollt Code aufgerufen wird, liegt das an einer unzureichenden Umsetzung. Bei MVC muss der Router dafür sorgen, dass nur die Controller- und sonst keine anderen Klassen aufgerufen werden können. Die Controller selbst sind so zu gestalten, dass nicht öffentliche Methoden nicht als public deklariert werden. Der Router routet nur zu public-Methoden. Somit ergeben sich ganz ohne Konfiguration keine ungewollten Code-Aufrufe.

      1b) Parameter im URL: Sofern Parameter das Routing bestimmen, stehen diese Parameter nicht für die Anwendung zur Verfügung.

      Wie begründest du denn diese These? Es kommt auf den Router an, was der aus dem Request für Daten extrahiert und weitergibt.

      Die Entwicklung von Anwendungen wird eingeschränkt und es ergeben sich unnötig komplizierte Abhängigkeiten. Im einfachsten Fall darf ein Entwickler keine Parameter festlegen oder verwenden, die für das Routing reserviert sind.

      Ich sehe da kein Problem, solange die Routen eindeutig aufgelöst werden können und der Router die benötigten Daten weitergibt.

      dedlfix.

      1. hi,

        Extra für Dich: Statische und Dynamische Routen

        Viel Spaß beim Lesen ;)

        Horst

        1. Tach!

          Extra für Dich: Statische und Dynamische Routen
          Viel Spaß beim Lesen ;)

          Danke, aber den hatte ich nicht.

          Ein Request auf einen bestimmten URL wird zu einer Klasse, zur Model Class geroutet.

          Es steht dir ja frei, einen Request von einem Model beantworten zu lassen, aber dann nenn das ganze bitte nicht MVC. Bei MVC wird der Request zu einem (Action)Controller (Klasse) und darin einer Action (Methode) geroutet.

          Model Class: Die Controller-Class, welche einem URL (ohne Parameter) zugeordent ist.

          Gemäß MVC beschreibt das Model die Daten und ist nicht der Controller. Der Controller ist ein eigenständiges Gebilde und behandelt üblicherweise den Request derart, dass er ein Model und eine View zusammenbringt, auf dass die Daten des Models von der View in die gewünschte Anzeigeform gebracht werden. Der Controller kann auch andere Aktionen mit dem Model durchgeführt werden, zum Beispiel die Kontrolle und Speicherung eingegebener Daten veranlassen.

          dedlfix.

          1. hi,

            Extra für Dich: Statische und Dynamische Routen
            Viel Spaß beim Lesen ;)

            Danke, aber den hatte ich nicht.

            Ein Kritiker ist wie eine Henne, die gackert, wenn andere Eier legen (Erich von Däniken).

            Danke Erich, der mit ungezählten dedlfixn zu tun hat ;)

            Horst Haselhuhn, Legehennenexperte