Url Rewriting et Symfony : Fantastique !

Juin 02, 07 Url Rewriting et Symfony : Fantastique !

URL Rewriting Symfony

Comme je l’ai expliqué précédemment, l’url rewriting est important, mais ce n’est pas toujours aisé à mettre en place, encore une fois Symfony va nous simplifier la vie, qui utilise en natif l’url rewriting de niveau 1, mais qui permet surtout une manipulation très simple de celui de niveau 2.

Url Rewriting par défaut

Par défaut Symfony utilise des url correspondant au module et à l’action en cours, ce qui donne pour la visualisation de l’article 55 :
http://www.monsite.com/article/show/id/55

Les variables sont automatiquement transformées : ?id=55 devenant /id/55

Les liens ressemblant ainsi à :

echo link_to ( « show », ‘article/show?id=’.$article->getId() )

Ce choix d’url rewriting est configuré par défaut dans le fichier /fo/config/routing.yml :

# La page d’accueil redirige vers le module main et vers l’action index
homepage:
    url:   /
    param: { module: main, action: index }
# Pour chaque index de module redirige vers l’action index
default_index:
    url:   /:module
    param: { action: index }
# Pour chaque module et chaque action redirige vers l’action correspondante
default:
    url:   /:module/:action/*

Url Rewriting totalement contrôlé

Mais voilà pour le référencement le niveau 2 est tout de même beaucoup plus intéressant, et Symfony est très bon à ce petit jeu.

Imaginons que nous ayons des rubriques et des articles, nous souhaitons des urls de type http://www.monsite.com/url-ma-rubrique/url-mon-article/ , les informations d’url étant tirés de la base de donnée et sans masque d’url (ex : rubrique-url-ma-rubrique/article-url-mon-article/), ce qui est trop facile.

Tout d’abord nous devons ajouter cette nouvelle configuration au début du fichier routing.yml :

 # Si j’ai le masque avec une url de type rubrique (rurl) et une de type article (aurl),
# je redirige vers l’action permalink du module article
article_by_aurl:
    url: /:rurl/:aurl
    param: { module: article, action: permalink }
# Redirige vers l’action index du module article avec comme variable id
article_by_id:
    url:  /article/index/id/:id
    param: { module: article, action: index }

rubrique_by_rurl:
    url:  /:rurl
     param: { module: main, action: permalink }

rubrique_by_id:
    url:  /main/index/id/:id
    param: { module: main, action: index }


Ensuite je dois créer ces 2 nouvelles actions Permalink dans chacune des classes actions des modules.

# Function à ajouter dans la classe /fo/module/rubrique/actions/actions.class.php
public function executePermalink() {

  # Vérifie qu’il existe bien une rubrique en ligne, sinon Erreur 404
  $rurl = $this->getRequestParameter('rurl') ;
  $c = new Criteria();
  $c->add( RubriquePeer::URL,$rurl );
  $c->add( RubriquePeer::EN_LIGNE , 1 );
  $rubrique = RubriquePeer::doSelectOne($c);
  $this->forward404Unless($rubrique) ;


  # Vérifie qu’il existe bien au moins un article en ligne pour cette rubrique,
  # sinon Erreur 404
  $c = new Criteria();
  $c->add( ArticlePeer::RUBRIQUE_ID, $rubrique->getId() );
  $c->add( ArticlePeer::EN_LIGNE , 1 );
  $cArticle = ArticlePeer::doCount($c);
  $this->forward404If($cArticle < 1) ;

  # Si tout ok, passe au module main et à l’action index avec la variable id
  $this->getRequest()->setParameter('id', $rubrique->getId());
  $this->forward(main, 'index');
}


# Function à ajouter dans la classe /fo/module/article/actions/actions.class.php
public function executePermalink()   {

  # Imaginons que toutes les rubriques sont en session pour éviter les accès à la base
  $allRubriques = sfContext::getInstance()->getUser()->getAttribute('allRubriques');

  # on vérifie qu’il existe bien une rubrique correspondant à la variable $rurl
  # sinon Erreur 404
  $rurl = $this->getRequestParameter('rurl') ;

  foreach($rzwRubrique as $rubrique) {
    if($rubrique->getUrl()== $rurl )
      $currentRubrique =  $rubrique;
    }
    $this->forward404Unless($currentRubrique);


    # on vérifie qu’il existe bien un article correspondant à la variable $aurl
    # sinon Erreur 404
    $aurl = $this->getRequestParameter('aurl') ;
    $c = new Criteria();
    $c->add( ArticlePeer::URL, $aurl );
    $c->add( ArticlePeer::RUBRIQUE_ID, $currentRubrique ->getId() );
    $c->add( ArticlePeer::EN_LIGNE , 1 );
    $article = ArticlePeer::doSelectOne($c);
    $this->forward404Unless($article);

    # Si tout ok, passe au module article et à l’action show avec la variable id
    $this->getRequest()->setParameter('id', $article->getId() );
    $this->forward('article', 'show');
}

7 Comments

  1. Redondo /

    salut,

    j'ai un petit problème avec routing :

    cvcandidat:
    url: /Profil/Cv/:Stripped_Title/
    param: { module: Cv, action: show }

    lorsque j'utilise deux niveau 'Profil' et 'Cv' le strippedTitle ne s'affiche pas sur les liens 🙁 …

    /index.php/Profil/Cv

    si je fais un seul niveau 'Cv' ou 'Profil' ça marche bien !?

    cvcandidat:
    url: /Cv/:Stripped_Title/
    param: { module: Cv, action: show }

    donne :
    /index.php/Cv/Reda_Makhchan

    est ce que les niveaux sont limiter quelque part?

    merçi d'avance 😉

  2. Bonjour Redondo,

    Je ne suis pas sûre d'avoir tout compris, mais il me semble, que dans ton cas il n'y a pas de raison d'utiliser Profil/CV.

    Car dans ce cas, Symfony va considérer qu'il existe un module Profil avec une Action CV et une variable strippedTitle.

    A noter que j'imagine qu'il existe une façon de faire ce que tu souhaites, mais là je ne vois pas.

  3. Salut Kaki,

    Ce problème est assez étrange, je n'ai pas d'idée, cependant je pense qu'il vaut mieux éviter de toucher au htaccess.

    Par ailleurs, je me demande en quoi cela pose un réel problème ?

  4. Bonjour David,

    Sous Symfony on ne touche pas au htaccess : JAMAIS.

    Tout est possible sans passer par lui, et en général c’est plus simple 🙂

  5. kapik /

    Bonjour!

    As tu une solution pour supprimer la variable « symfony » qui apparait dans l’url qui semble etre la session ? (je suis sous ovh)
    Si ta une solution hésite pô 😉

    By

  6. @kapik
    effectivement la variable « symfony » correspond à l’ID de Session

    pour régler ton problème sous OVH il suffit de mettre

    ini_set(‘session.use_cookies’, true);
    ini_set(‘session.use_only_cookies’, true);
    ini_set(‘session.use_trans_sid’, false);
    ini_set(‘url_rewriter.tags’, »);

    au début de ton fichier index.php

    tchao

  7. petite correction dû à des problèmes dans l’affichage 🙂 :


    ini_set('session.use_cookies', true);
    ini_set('session.use_only_cookies', true);
    ini_set('session.use_trans_sid', false);
    ini_set('url_rewriter.tags', ''); // 2 quotes :)

Leave a Comment

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *