0 follower

URL-Management

Für ein umfassendes URL-Management sind zwei Seiten zu berücksichtigen. Zum einen muss die Anwendung bei einem eingehenden Benutzer-Request die vorliegende URL auswerten, also in für sie verständliche Parameter übersetzen. Zum anderen muss man mit der Anwendung auch ebensolche URLs erzeugen können. Bei einer Yii-Applikation werden diese Aufgaben von CUrlManager übernommen.

1. Erstellen von URLs

Obwohl man in Views statische URLs verwenden kann, bleibt man meist flexibler, wenn man sie dynamisch erzeugt:

$url=$this->createUrl($route,$params);

wobei $this sich auf die Controller-Instanz bezieht. $route gibt die Route des Requests an und $params eine Liste von GET-Parametern, die an die URL angehängt werden sollen.

Standardmässig werden mit createUrl erstellte URLs im sogenannten get-Format erzeugt. Für die Werte $route='post/read' und $params=array('id'=>100) würden wir zum Beispiel die folgende URL erhalten:

/index.php?r=post/read&id=100

wobei Parameter im Anfragestring (der Teil hinter dem ?) als Liste von Name=Wert Elementen enthalten sind, die durch eine UND-Zeichen (&) getrennt werden. Der Parameter r gibt die angeforderte Route an. Dieses URL-Format ist nicht sehr anwenderfreundlich, da es etliche Sonderzeichen enthält.

Mit dem sogenannten path-Format (Pfad-Format) können wir die obige URL etwas sauberer und selbsterklärender machen. Es entfernt den Anfragestring und bringt die GET-Parameter in der Pfadangabe der URL unter:

/index.php/post/read/id/100

Um das URL-Format zu ändern, sollten wir die Anwendungskomponente urlManager konfigurieren, so dass createUrl automatisch das neue Format verwendet und die Anwendung die neuen URLs auch richtig interpretiert:

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
        ),
    ),
);

Beachten Sie, dass wir die Klasse für die urlManager-Komponente nicht angeben müssen, da sie von CWebApplication bereits mit dem Wert CUrlManager vorbelegt wurde.

Tipp: URLs die mit createUrl erzeugt werden, sind relativ. Um absolute URLs zu erhalten, können wir ihnen entweder Yii::app()->hostInfo voranstellen, oder createAbsoluteUrl aufrufen.

2. Benutzerfreundliche URLs

Wenn wir das URL-Format path verwenden, können wir noch anwenderfreundlichere URLs erhalten, indem wir zusätzlich einige URL-Regeln angeben. Zum Beispiel können wir eine kurze URL wie /post/100 statt der langen /index.php/post/read/id/100 erzeugen. URL-Regeln werden von CUrlManager sowohl zum Erstellen als auch zum Auswerten von URLs verwendet.

Um URL-Regeln anzugeben, müssen wir die Eigenschaft rules der urlManager-Komponente konfigurieren:::

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
            'rules'=>array(
                'pattern1'=>'route1',
                'pattern2'=>'route2',
                'pattern3'=>'route3',
            ),
        ),
    ),
);

Die Regeln werden als Array von Suchmuster-Routen-Paaren angegeben, bei denen jeder Eintrag sich auf eine einzelne Regel bezieht. Das Suchmuster (engl.: pattern) einer Regel ist ein String, der zum Auffinden der Pfadangaben in einer URL verwendet wird. Die Route sollte einer gültigen Controller-Route entsprechen.

Info: Seit version 1.0.6 kann eine Regel über die Optionen urlSuffix und caseSensitive noch weiter angepasst werden. Und seit Version 1.0.8 können bei einer Regel auch defaultParams angegeben werden. Sie stehen für eine Reihe von Schlüssel-Werte-Paaren, die in $_GET übernommen werden sollen. Zum Anpassen der Regeln müssen wir den Routenteil als Array wie folgt angeben:

'pattern1'=>array('route1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)

Verwenden von benannten Parametern

Eine Regel kann mit einigen GET-Parametern verknüpft werden. Diese GET-Parameter erscheinen innerhalb der Regel in diesem Format:

<ParamName:ParamMuster>

wobei ParamName den Namen des GET-Parameters angibt und das optionale ParamMuster einen regulären Ausdruck, der für das Auffinden dieses Parameters verwendet werden soll. Falls ParamMuster nicht angegeben wird, bedeutet das, dass alle Zeichen außer dem Schrägstrich / als Parameterwert verwendet werden. Beim Erstellen einer URL werden diese Parameterplatzhalter durch die entsprechenden Parameterwerte ersetzt. Und beim Auswerten einer URL werden die entsprechenden GET-Parameter mit den gefundenen Werten gefüllt.

Sehen wir uns einige Beispiele an, um zu zeigen, wie URL-Regeln funktionieren. Nehmen wir an, wir verwenden diese drei Regeln:

array(
    'posts'=>'post/list',
    'post/<id:\d+>'=>'post/read',
    'post/<year:\d{4}>/<title>'=>'post/read',
)
  • Rufen wir $this->createUrl('post/list') auf, erzeugt dies /index.php/posts. Die erste Regel wird angewendet.

  • Rufen wir $this->createUrl('post/read',array('id'=>100)), erhalten wir /index.php/post/100. Die zweite Regel wird angewendet.

  • Rufen wir $this->createUrl('post/read',array('year'=>2008, 'title'=>'a sample post')) auf, erzeugt dies /index.php/post/2008/a%20sample%20post. Die dritte Regel wird angewendet.

  • Rufen wir $this->createUrl('post/read') auf, liefert dies /index.php/post/read. Keine der Regeln wird angewendet.

Zusammenfassend kann man sagen, dass beim Aufruf von createUrl anhand der übergebenen Route- und GET-Parameter entschieden wird, welche Regel zum Einsatz kommt. Eine Regel wird dann zur Erzeugung der URL verwendet, wenn jeder Parameter aus der Regel in den an createUrl übergebenen GET-Parametern vorgefunden wird und außerdem die Route der Regel mit der übergebenen Route übereinstimmt.

Wenn an createUrl mehr GET-Parameter übergeben wurden, als in einer Regel vorkommen, tauchen die zusätzlichen Parameter im Anfragestring auf. Rufen wir zum Beispiel $this->createUrl('post/read', array('id'=>100, 'year'=>2008)) auf, liefert uns das /index.php/post/100?year=2008. Um diese zusätzlichen Parameter in der Pfadangabe erscheinen zu lassen, sollten wir /* an eine Regel anhängen. Somit wird diese URL mit der Regel post/<id:\d+>/* zu /index.php/post/100/year/2008.

Wie erwähnt dienen URL-Regeln auch zum Auswerten von angeforderten URLs. Normalerweise ist das der umgekehrte Fall zum Erstellen einer URL. Wenn ein Anwender zum Beispiel /index.php/post/100 anfordert, kommt die zweite der obigen Regeln zum Einsatz. Sie löst die Route zu post/read und die GET-Parameter zu array('id'=>100) (erreichbar über $_GET) auf.

Hinweis: Der Einsatz von URL-Regeln verringert die Leistungsfähigkeit einer Anwendung. Das liegt daran, dass CUrlManager beim Auswerten einer URL für jede Regel prüft, ob sie auf die Anfrage passt, bis eine passende Regel gefunden wurde. Je mehr Regeln definiert wurden, desto größer ist die Auswirkung auf die Leistungsfähigkeit. Eine Webanwendung mit hohem Traffic-Aufkommen sollte daher die Anzahl ihrer URL-Regeln minimieren.

Parametrisierte Routen

Seit Version 1.0.5 können wir benannte Parameter im Routen-Teil einer Regel ansprechen. Dadurch kann die Regel je nach Suchkriterium auf mehrere Routen angewendet werden. Es kann auch helfen, die Anzahl der benötigten Regeln in einer Anwendung zu minimieren und dadurch die gesamte Leistungsfähigkeit zu steigern.

Wir zeigen am folgenden Beispiel, wie Routen mit benannten Parametern parametrisiert werden:

array(
    '<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>' => '<_c>/<_a>',
    '<_c:(post|comment)>/<id:\d+>' => '<_c>/read',
    '<_c:(post|comment)>s' => '<_c>/list',
)

Hier verwenden wir zwei benannte Parameter im Route-Teil der Regel: _c und _a. Ersterer gilt, wenn die Controller-ID entweder post oder commentist, während der zweite auf die Action-IDs create, update oder delete passt. Sie können die Parameter anders benennen, solange sie nicht in Konflikt mit anderen GET-Parametern in der URL geraten.

Wenn wir obige Regeln verwenden, wird die URL /index.php/post/123/create in die Route post/create mit den GET-Parametern id=123 übersetzt. Und bei gegebener Route comment/list mit dem GET-Parameter page=2 wird die URL /index.php/comments?page=2 erzeugt.

Verbergen von index.php

Wir können eine weitere Maßnahme zum Bereinigen unserer URLs durchführen: das Verbergen des Eingangsscripts index.php in der URL. Dazu müssen wir sowohl den Webserver als auch die urlManager-Komponente konfigurieren.

Zunächst richten wir den Webserver so ein, dass eine URL, bei der das Eingangsscript fehlt, immer noch vom Eingangsscript bearbeitet wird. Im Falle des Apache HTTP-Servers erreichen wir das, indem wir die Rewrite-Engine (sinngem.: Umschreibemaschine) einschalten und einige Rewrite-Rules (sinngem.: Umschreiberegeln) definieren. Wir können dazu die Datei /wwwroot/blog/.htaccess mit folgendem Inhalt anlegen. Beachten Sie, dass der selbe Inhalt auch direkt in der Apache-Konfiguration in einem Directory-Element für /wwwroot/blog abgelegt werden kann.

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on

# Verwende Verzeichnis oder Datei, wenn sie vorhanden sind
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Leite andernfalls auf index.php um
RewriteRule . index.php

Dann setzen wir die Eigenschaft showScriptName in der urlManager-Komponente auf false.

Jetzt erhalten wir beim Aufruf von $this->createUrl('post/read', array('id'=>100)) die URL /post/100. Und noch wichtiger: Diese URL wird auch korrekt von unserer Anwendung erkannt.

URL-Endung vortäuschen

Wir können auch Endungen an unsere URLs anhängen. Aus /post/100 können wir zum Beispiel /post/100.html machen. Das sieht dann noch mehr wie eine URL zu einer statischen Webseite aus. Setzen Sie dazu einfach die gewünschte Endung über die Eigenschaft urlSuffix der urlManager-Komponente.