1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect3 id="zend.controller.router.routes.regex">
<title>Zend_Controller_Router_Route_Regex</title>
<para>
Zusätzlich zu den standard statischen Routetypen, ist ein Regular Expression Routetyp
vorhanden. Diese Route bietet mehr Power und Flexibilität als die anderen, aber auf leichten
Kosten von Komplexität. Wärend der selben Zeit, sollte Sie schneller als die Standardroute
sein.
</para>
<para>
Wie die Standardroute, muß diese Route mit einer Routendefinition und einigen Standardwerten
initialisiert werden. Lasst uns eine Archivroute als Beispiel erstellen, ähnlich der zuletzt
definierten, nur das dieses Mal die Regex Route verwendet wird:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array(
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
]]></programlisting>
<para>
Jedes definierte Regex Subpattern wird in das Anfrageobjekt injiziiert. Mit dem obigen
Beispiel, nachdem <filename>http://domain.com/archive/2006</filename> erfolgreich geprüft
wurde, kann das resultierende Wertearray so aussehen:
</para>
<programlisting language="php"><![CDATA[
$values = array(
1 => '2006',
'controller' => 'archive',
'action' => 'show'
);
]]></programlisting>
<note>
<para>
Führende und folgende Schrägstriche werden von der <acronym>URL</acronym> im Router vor
dem Vergleich entfernt. Als Ergebnis, wird ein Vergleich der <acronym>URL</acronym>
<filename>http://domain.com/foo/bar/</filename>, ein Regex von
<filename>foo/bar</filename> inkludieren, aber nicht <filename>/foo/bar</filename>.
</para>
</note>
<note>
<para>
Zeilenbeginn und Endanker (normalerweise '^' und '$') werden automatisch allen
Ausdrücken vor- und nachgesetzt. Deswegen sollten Sie nicht in den Regular Expressions
verwendet werden, und der komplette String sollte entsprechen.
</para>
</note>
<note>
<para>
Diese Routeklasse verwendet das '<emphasis>#</emphasis>' Zeichen als Begrenzer. Das
bedeutet das ein Hashzeichen ('#') kommentiert werden muß aber keine Schrägstriche ('/')
in der Routendefinition. Da das '#' Zeichen (Anker genannt) selben an einen Webserver
übergeben wird, wird man dieses Zeichen selten in der eigenen regex verwenden.
</para>
</note>
<para>
Die Inhalte von definierten Subpattern können auf dem üblichen Weg bekommen werden:
</para>
<programlisting language="php"><![CDATA[
public function showAction()
{
$request = $this->getRequest();
$year = $request->getParam(1); // $year = '2006';
}
]]></programlisting>
<note>
<para>Beachte das der Schlüssel ein Integer ist (1) anstatt ein String ('1').</para>
</note>
<para>
Diese Route wird jetzt noch nicht exakt gleich wie Ihr Gegenspieler, die Standardroute,
arbeiten da der Standard für 'year' noch nicht gesetzt ist. Und was jetzt noch nicht
offensichtlich ist, ist das wir ein Problem mit endenden Schrägstrichen haben, selbst wenn
wir einen Standard für das Jahr definieren und das Subpattern optional machen. Die Lösung
ist, den ganzen year Teil optional zu nachen zusammen mit dem Schrägstrich, aber nur den
nummerischen Teil zu holen:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive(?:/(\d+))?',
array(
1 => '2006',
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
]]></programlisting>
<para>
Jetzt betrachten wir das Problem das möglicherweise schon selbst gefunden wurde. Die
Verwendung von Integer basierten Schlüsseln für Parameter ist keine einfach zu handhabende
Lösung und kann, während einer langen Laufzeit, potentiell problematisch sein. Hier kommt der
dritte Parameter ins Spiel. Dieser Parameter ist ein assoziatives Array das einer Karte von
Regex Subpatterns zu Parametern benannten Schlüsseln entspricht. Betrachten wir ein
einfacheres Beispiel:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array(
'controller' => 'archive',
'action' => 'show'
),
array(
1 => 'year'
)
);
$router->addRoute('archive', $route);
]]></programlisting>
<para>
Als Ergebnis werden die folgenden Werte in die Anfrage injiziiert:
</para>
<programlisting language="php"><![CDATA[
$values = array(
'year' => '2006',
'controller' => 'archive',
'action' => 'show'
);
]]></programlisting>
<para>
Die Karte kann in jede Richtung definiert werden damit Sie in jeder Umgebung funktioniert.
Schlüssel können Variablennamen oder Indezes von Subpattern enthalten:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array(1 => 'year')
);
// ODER
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array('year' => 1)
);
]]></programlisting>
<note>
<para>
Schlüssel von Subpattern müssen durch Integer repräsentiert werden.
</para>
</note>
<para>
Es gilt zu beachten das der nummerische Index in den Anfragewerten jetzt weg ist und eine
benannte Variable statt Ihm angezeigt wird. Natürlich können nummerische und benannte
Variablen gemischt werden wenn das gewünscht ist:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)/page/(\d+)',
array( ... ),
array('year' => 1)
);
]]></programlisting>
<para>
Das führt zu gemischten Werten die in der Anfrage vorhanden sind. Als Beispiel, wird die
<acronym>URL</acronym> <filename>http://domain.com/archive/2006/page/10</filename> zu
folgenden Werte führen:
</para>
<programlisting language="php"><![CDATA[
$values = array(
'year' => '2006',
2 => 10,
'controller' => 'archive',
'action' => 'show'
);
]]></programlisting>
<para>
Da Regex Patterns nicht einfach rückgängig zu machen sind, muß eine umgekehrte
<acronym>URL</acronym> vorbereitet werden wenn ein <acronym>URL</acronym> Helfer verwendet
werden soll oder sogar eine Herstellungsmethode dieser Klasse. Dieser umgekehrte Pfad wird
durch einen String dargestellt der durch <methodname>sprintf()</methodname> durchsucht
werden kann und als vierter Parameter definiert wird:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array('year' => 1),
'archive/%s'
);
]]></programlisting>
<para>
Da all das bereits etwas ist das durch die Bedeutung eines standardmäßigen Route Objektes
möglich ist kommt natürlich die Frage aus worin der Vorteil einer regex Route besteht?
Primär erlaubt Sie jeden Typ von <acronym>URL</acronym> zu beschreiben ohne irgendwelche
Einschränkungen. Angenommen man hat einen Blog und will eine <acronym>URL</acronym> wie die
folgende erstellen:
<filename>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</filename>, und muß
das jetzt Pfad Element <filename>01-Using_the_Regex_Router.html</filename> bearbeiten, in
eine Artikel ID und eine Artikel Titel oder Beschreibung; das ist nicht möglich mit der
Standardroute. Mit der Regex Route ist etwas wie die folgende Lösung möglich:
</para>
<programlisting language="php"><![CDATA[
$route = new Zend_Controller_Router_Route_Regex(
'blog/archive/(\d+)-(.+)\.html',
array(
'controller' => 'blog',
'action' => 'view'
),
array(
1 => 'id',
2 => 'description'
),
'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);
]]></programlisting>
<para>
Wie man sieht, fügt das ein enormes Potential von Flexibilität zur Stnadardroute hinzu.
</para>
</sect3>
<!--
vim:se ts=4 sw=4 et:
-->
|