Development

Documentation/fr_FR/book/trunk/routing (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of Documentation/fr_FR/book/trunk/routing

Show
Ignore:
Author:
mikl63 (IP: 193.41.238.221)
Timestamp:
12/28/06 14:32:45 (11 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/fr_FR/book/trunk/routing

    v0 v1  
     1Comment modifier la politique de reecriture 
     2============================= 
     3 
     4Overview 
     5-------- 
     6 
     7Un des problemes les plus importants posé par un framework est l'aspect des URLs générés: elles sont souvent longues, complexe et mal réferencable par les moteurs de recherches. Symfony propose un nouveau systeme de *routing* qui vous donnera le controle total sur les adresses de vos applications. 
     8 
     9Introduction 
     10------------ 
     11 
     12Prenons le cas d'une application de type blog ou les utilisateurs publient des articles. Avec symfony, pour afficher cet article, vous ne voulez pas d'une URL comme ca: 
     13 
     14    http://myapp.example.com/index.php/article/read/id/100 
     15 
     16Cette URL appelle l'action `read` du module `article` avec pour parametre `id` : 100 
     17 
     18Pour optimiser le travail des moteur de recherche dans l'indexation des pages des sites dynamiques, et rendre les URLs plus lisibles, quelques outils de blog propose une option *permalink*. Un permalink (lien permanent) est une adresse definie et permanente pour les favoris des navigateurs, et les moteurs de recherche. En reprenant l'exemple précedent, le permalink serait: 
     19 
     20    http://myapp.example.com/index.php/article/permalink/title/my_article_title 
     21 
     22La seule difference avec la premiere URL est l'utilisation de mots clefs plus parlant. L'action `permalink` a pour but de   convertir la variable `title` dans l'`id` de l'article, en cherchant en base l'adresse d'une page permanente ou rediriger le moteur de recherche. 
     23 
     24Cette methode est capable d'afficher des URLs encore plus simple et parlante, par exemple: 
     25 
     26    http://myapp.example.com/article/my_article_title 
     27    // ou pourquoi pas 
     28    http://myapp.example.com/2005/06/25/my_article_title 
     29 
     30La facon la plus simple est d'utiliser le module `mod_rewrite` du serveur Apache, avec l'URL rewriting. L'URL rewriting convertit les URLs en quelquechose comprehensible pour Apache: 
     31 
     321. Apache recoit une requete pour `http://myapp.example.com/2005/06/25/my_article_title` 
     332. `mod_rewrite` convertit cette URL en `http://myapp.example.com/index.php/article/read/title/my_article_title` 
     343. Apache sait qu'il doit executer `index.php` avec `/article/read/title/my_article_title` comme valeur pour le `path_info` 
     35 
     36Cette solution a deux conditions necessaires: 
     37 
     38*   vous avez besoin d'un serveur Apache avec le module `mod_rewrite` 
     39*   l'URL rewriting est la seule solution 
     40 
     41En depit des faits, si vous voulez creer une URL vers cet article, vous aurez besoin de convertir manuellement la base de l'URL en une "smart" (plus parlante) URL. L'URL entré (utilisé par le module `mod_rewrite`) et l'URL généré (utilisé par l'application) sont completement differente 
     42 
     43Symfony peut en natif convertir les URLs générés et interpretés les URLs entrées. Par consequent, vous pouvez creer des associations entre les URLs et les controller. Cette reecriture est appelé *routing* dans symfony, relié a un fichier de configuration nommmé `routing.yml` que vous pouvez retrouver dans le repertoire `config/` de chaque application.    
     44 
     45//MIKA 
     46 
     47Routing input URLs 
     48------------------ 
     49 
     50### Rules and patterns 
     51 
     52The `routing.yml` contains **rules**, or bijective associations between a URL pattern and the "real" request parameter. A typical rule file contains: 
     53 
     54* a label, which is there for legibility and can be used by the [link helpers](templating_link_helpers.txt) 
     55* an `url` key showing the pattern to be matched 
     56* a `param` used to set default values for some of the arguments of the "real" call 
     57 
     58Here is an extract of the `routing.yml` file that illustrates the rewriting of our example blog URL: 
     59 
     60    article_by_title_with_date: 
     61      url:    /:year/:month/:day/:title 
     62      param:  { module: article, action: permalink } 
     63 
     64The rule stipulates that every request showing the pattern `/:year/:month/:day/:title` will have to be transformed into a call to the `permalink` action of the `article` module with arguments `year`, `month`, `day` and `title` taken from the base URL. 
     65 
     66So the example URL 
     67 
     68    http://myapp.example.com/index.php/2005/06/25/my_article_title 
     69 
     70Will be understood as if written 
     71 
     72    http://myapp.example.com/index.php/article/permalink/year/2005/month/06/day/25/title/my_article_title 
     73 
     74...and call the `permalink` action of the `article` module with the following arguments: 
     75 
     76    [php] 
     77    $this->getRequestParameter('year') => 2005 
     78    $this->getRequestParameter('month') => 06 
     79    $this->getRequestParameter('day') => 25 
     80    $this->getRequestParameter('title') => my_article_title 
     81 
     82Let's add a second rule to handle URLs like: 
     83 
     84    http://myapp.example.com/index.php/article/100 
     85 
     86Simply add the following lines in the `routing.yml` file: 
     87 
     88    article_by_id: 
     89      url:          /article/:id 
     90      param:        { module: article, action: read } 
     91 
     92Notice that in the pattern, the word `article` is a string whereas `id` is a variable (because it starts with a `:`). 
     93 
     94>**Note**: you smart readers may have guessed that as soon as a rule such as the one mentioned above is added, the default rule (which is `/:module/:action/*`) will not work anymore with the `article` module, because the module name will match the pattern `/article/:id` first. If you start creating rules with strings that match the names of your modules, you probably need to change the default rule to something like: 
     95> 
     96>     default: 
     97        url:   /action/:module/:action/* 
     98 
     99### Pattern constraints 
     100 
     101Now what if you needed to have access to articles from their title: 
     102 
     103    http://myapp.example.com/index.php/article/my_article_title 
     104 
     105Well, this looks problematic. This URL should be routed to the `permalink` action, but it already satisfies the `articl_by_id` rule and will be automatically routed to the `read` action. To solve this issue, each entry can take a third parameter called `requirements` to specify constraints in the pattern (in the shape of a regular expression). That means that you can modify the previous rule to route URLs to `read` only if the `id` argument is an integer: 
     106 
     107    article_by_id: 
     108      url:          /article/:id 
     109      param:        { module: article, action: read } 
     110      requirements: { id: ^\d+$ } 
     111 
     112Now you can add a third rule to gain access to articles from their title: 
     113 
     114    article_by_title: 
     115      url:          /article/:permalink 
     116      param:        { module: article, action: permalink } 
     117 
     118Rules are ordered and the routing engine takes the first one that satisfies the pattern and the pattern constraints. That's why you don't need to add a constraint to the last rule (specifying that `permalink` can not be an integer): 
     119 
     120*   `/article/100` matches the first rule and will be handed to `read` 
     121*   `/article/my_article_title` doesn't match the first rule but matches the second, so it will be handed to `permalink` 
     122 
     123Now that you know about pattern constraints, that would be a good thing to add some to the very first rule: 
     124 
     125    article_by_title_with_date: 
     126      url:          /:year/:month/:day/:title 
     127      param:        { module: article, action: permalink } 
     128      requirements: { year: ^\d{4}$, month: ^\d\d$, day: ^\d\d$ } 
     129 
     130The routing engine allows you to handle a large set of rules; however, you have to add the most precise constraints and order them properly so that no ambiguity may arise. 
     131 
     132>**Hint**: the YAML syntax allows you to write more legible configuration files if you write associative arrays line by line. For instance, the last rule can also be written: 
     133> 
     134>     article_by_title_with_date: 
     135>       url:        /:year/:month/:day/:title 
     136>       param: 
     137>         module:   article 
     138>         action:   permalink 
     139>       requirements: 
     140>         year:     ^\d{4}$ 
     141>         month:    ^\d\d$ 
     142>         day:      ^\d\d$ 
     143 
     144### Default values 
     145 
     146Here is a new example: 
     147 
     148    article_by_id: 
     149      url:          /article/:id 
     150      param:        { module: article, action: read, id: 1 } 
     151 
     152This rule defines the default value for the `id` argument. This means that a `/article/100` URL will behave as previously, but in addition, the URL `/article/` will be equivalent to `/article/1`. The default parameters don't need to be variables found in the pattern. Consider the following example: 
     153 
     154    article_by_id: 
     155      url:          /article/:id 
     156      param:        { module: article, action: read, id: 1, display: true } 
     157 
     158The `display` argument will be passed with the value `true`, whatever the pattern. And, if you look carefully, you will see that `article` and `read` are also default values for variables not found in the pattern. 
     159 
     160### Default rules 
     161 
     162The default `routing.yml` has a few default rules. To allow the old style 'module/action' URLs to work: 
     163 
     164    default: 
     165      url:   /:module/:action/* 
     166 
     167As mentioned above, you may need to change this rule if some of your modules have names that can match other patterns. 
     168 
     169The other default rules are used to set the root URL to point the default module and action: 
     170 
     171    homepage: 
     172      url:   / 
     173      param: { module: #SF_DEFAULT_MODULE#, action: #SF_DEFAULT_ACTION# } 
     174 
     175    default_index: 
     176      url:   /:module 
     177      param: { action: #SF_DEFAULT_ACTION# } 
     178 
     179The default module and action themselves are configured in the `settings.yml` file. 
     180 
     181### How to avoid mentioning the front controller ? 
     182 
     183In all previous examples, the URLs still have contain the `index.php` header to be processed. This is because the front controller has to be called first so that the routing feature can work. 
     184 
     185If you have the `mod_rewrite` module activated, use the following configuration (which is the default configuration bundled with symfony in the `myproject/web/.htaccess` file) to tell apache to call the `index.php` file by default: 
     186 
     187    Options +FollowSymLinks +ExecCGI 
     188 
     189    RewriteEngine On 
     190 
     191    # we skip all files with .something 
     192    RewriteCond %{REQUEST_URI} \..+$ 
     193    RewriteRule .* - [L] 
     194 
     195    # we check if the .html version is here (caching) 
     196    RewriteRule ^$ index.html [QSA] 
     197    RewriteRule ^([^.]+)$ $1.html [QSA] 
     198    RewriteCond %{REQUEST_FILENAME} !-f 
     199 
     200    # if no rule matched the url, we redirect to our front web controller 
     201    RewriteRule ^(.*)$ index.php [QSA,L] 
     202 
     203    # big crash from our front web controller 
     204    ErrorDocument 500 "<h2>Application error</h2>Symfony application failed to start properly" 
     205 
     206Now a call to 
     207 
     208    http://myapp.example.com/article/read/id/100 
     209 
     210Will be properly understood as 
     211 
     212    http://myapp.example.com/index.php/article/read/id/100 
     213 
     214Outputting smart URLs 
     215-------------------- 
     216 
     217### Matching patterns 
     218 
     219Until now, the `routing.yml` file only helped to reproduce the `mod_rewrite` behaviour, i.e. understanding properly formatted URLs. The good news is, now that you defined routing rules, they will be automatically used to transform URLs *from* your application. 
     220 
     221In symfony, when you write a link in a template, you use the `link_to()` helper: 
     222 
     223    [php] 
     224    <?php echo link_to($article->getTitle(), '/article/read?id='.$article->getId()) ?> 
     225 
     226To read more about this helper, check the chapter about [link helpers](templating_link_helpers.txt). With the default routing configuration, this outputs the following HTML code: 
     227 
     228    [php] 
     229    <a href="/index.php/article/read/id/100">my_article_title</a> 
     230 
     231But since you wrote routing rules, symfony will automatically interpret them in the other way and generate: 
     232 
     233    [php] 
     234    <a href="/index.php/article/100">my_article_title</a> 
     235 
     236The rules will be parsed with the same order as for the interpretation of an input request, and the first rule matching the arguments of the `link_to()` second argument will determine the pattern to be used to create the output URL. 
     237 
     238### Getting rid of `index.php` 
     239 
     240As for now, the link helpers still output the name of the front controller. If the web server is configured to handle calls without mention of the front controller, as described above, the routing system can be told not to include it. 
     241 
     242This is done in the application `settings.yml` configuration file. To turn off the display of the front controller in the production environment, write: 
     243 
     244    prod: 
     245      .settings 
     246        no_script_name:  on 
     247 
     248### Adding a `.html` 
     249 
     250Having an output URL like: 
     251 
     252    http://myapp.example.com/2005/06/25/my_article_title 
     253 
     254is not bad, but 
     255 
     256    http://myapp.example.com/2005/06/25/my_article_title.html 
     257 
     258is much better. It changes the way your application is perceived by the user, from "a dynamic thing with cryptic calls" to "a deep and well organized web directory". All that with a simple suffix. In addition, the search engines will grant more stability to a page named like that. 
     259 
     260As before, this is simply done in the `settings.yml` configuration file of the application: 
     261 
     262    prod: 
     263      .settings 
     264        suffix:         .html 
     265 
     266The default suffix is set to `.`, which means that nothing is appended to the end of the routed url. You can specify any type of suffix, including `/` to have an URL looking like: 
     267 
     268    http://myapp.example.com/2005/06/25/my_article_title/ 
     269 
     270It is sometimes necessary to specify a suffix for a unique routing rule. In that case, directly write the suffix in the related `url:` line of the `routing.yml` file; the global suffix will be ignored. 
     271 
     272    article_list_feed: 
     273      url:          /latest_articles.rss 
     274      param:        { module: article, action: list, type: rss } 
     275 
     276    update_directory: 
     277      url:          /updates/ 
     278      param:        { module: update, action: list } 
     279 
     280Retrieve information about the current route 
     281-------------------------------------------- 
     282 
     283If you need to retrieve information about the current route, for instance to prepare a future 'back to page xxx' link, you should use the methods of the `sfRouting` object. For instance, if your `routing.yml` defines: 
     284 
     285    my_rule: 
     286      url:   /call_my_rule 
     287      param: { module: mymodule, action: myaction } 
     288 
     289Use the following calls in the action: 
     290 
     291    [php] 
     292    // if you require an URL like 
     293    http://myapp.example.com/call_my_rule/param1/xxx/param2/yyy 
     294 
     295    $uri = sfRouting::getInstance()->getCurrentInternalUri(); 
     296    // will return 'mymodule/myaction?param1=xxx&param2=yyy' 
     297 
     298    $uri = sfRouting::getInstance()->getCurrentInternalUri(true); 
     299    // will return '@myrule?param1=xxx&param2=yyy' 
     300 
     301    $route = sfRouting::getInstance()->getCurrentRouteName(); 
     302    // will return 'myrule' 
     303 
     304The URIs returned by the `->getCurrentInternalUri()` method can be used in a call to a `link_to()` helper. 
     305 
     306In addition, you might want to get the first or the last action called in a template. The following variables are automatically updated at each request and are available to templates: 
     307 
     308    $sf_first_action 
     309    $sf_first_module 
     310    $sf_last_action 
     311    $sf_last_module 
     312 
     313You might ask: Why can't I simply retrieve the current module/action ? Because the calls to actions is a stack, and several calls can be made for a unique request. For instance, if the end of an action contents a `forward` statement, several actions will be called.