Laravel 4

Laravel 4 : chapitre 4 : Les routes

Voyons le fonctionnement d’une requête avec Laravel. Un requête commence par être traitée par le .htaccess pour être obligatoirement dirigée sur  le fichier index.php. Celui-ce commence par charger le fichier autoload.php :

require __DIR__.'/../bootstrap/autoload.php';

C’est à ce niveau que sont effectués les chargement des classes. Ensuite index.php charge le fichier start.php :

$app = require_once __DIR__.'/../bootstrap/start.php';

Ce fichier start.php se situe dans le dossier bootstrap de Laravel. C’est dans ce fichier que l’application est créée :

$app = new Illuminate\Foundation\Application;

L’objet application est le conteneur IoC. Ensuite sont définis le chemin de l’application, l’environnement, et le fichier des routes est chargé. On peut alors traiter la requpete et envoyer une réponse au demandeur.

Structure des URL

Les URL utilisées par Laravel ont cette structure :

http://mondomaine.org/ma/page

Ma partie ma/page peut être constitué par tout ce que vous voulez, avec autant de découpages que nécessaire, comme nous allons le voir tout au long des articles.

Les routes de base

La requête est analysée et comparée aux chemins définis dans le fichier app/route.php.

Si vous l’ouvrez vous ne trouvez que ce code :

Route::get('/', function()
{
	return View::make('hello');
});

Changez-le pour celui-ci :

Route::get('/', function()
{
	return 'coucou';
});

Si vous lancez l’application avec l’URI http://localhost/laravel/public/ vous obtenez le message « coucou » à l’écran, ce qui montre que l’URI est bien traitée par ce code (je rappelle que je pars de l’hypothèse que vous testez Laravel 4 en local dans un dossier nommé « laravel »).

La syntaxe est simple, vous indiquez le type de requête, ici on a get mais vous pouvez utiliser aussi post comme nous allons le voir plus loin (sont aussi gérés put et delete). Vous avez ensuite deux paramètres dont le premier est le chemin (ici c’est la racine représentée par « / »), le second paramètre est une fonction anonyme contenant le traitement.

Faisons un autre essai avec une autre URL :

Route::get('login', function()
{
	return 'login';
});

Ici l’URI correspondante est http://localhost/laravel/public/login.

Remarquez qu’on n’ajoute pas le signe « / » dans ce cas devant « login ». le seul cas où on l’utilise est celui de la racine. Par contre maintenant si vous utilisez l’URL http://localhost/laravel/public/ vous obtenez un message d’erreur puisque nous n’avons plus de chemin défini pour cette URL :

img97

Sur un site en production il faudra évidemment éviter ce genre de message, mais en cours de développement c’est indispensable.

Une route avec post

Prenons un exemple de route avec une requête de type post. Pour cela créons un petit formulaire nommé test.html et placé dans le dossier public :

<form action="log" method="post">
	<input type="text" name="nom" />
	<input type="submit" name="Envoyer" />
</form>

Et prévoyons la route pour récupérer l’information :

Route::post('log', function()
{
	return Input::get('nom');
});

Surprised Nous verrons en détail la récupération des entrées dans un autre chapitre mais la clarté de la syntaxe de Laravel doit vous rendre cette écriture déjà évidente.

En réponse à l’URL : http://localhost/laravel/public/test.html nous obtenons le formulaire :

img12Et si nous entrons « toto » comme dans le cas de cette image, ce nom doit s’afficher comme réponse à l’écran, ce qui montre que les variables « post » sont bien prises en compte.

 Les paramètres

Il est classique de transmettre des paramètres dans une requête de type « get », il faut alors pouvoir récupérer ces paramètres. Voici un exemple :

Route::get('article/{numero}', function($numero)
{
	return "Le numéro de l'article est $numero";
});

Exemple d’URL :  http://localhost/laravel/public/article/24

Remarquez la syntaxe, le paramètre est placé entre accolades, on reprend son nom comme paramètre de la fonction et on n’a plus qu’à l’utiliser.

Avec cette syntaxe si vous ne mettez aucun paramètre vous obtenez un message d’erreur. Il est possible de rendre le paramètre optionnel en faisant suivre un point d’interrogation à son nom. Mais  il faut prévoir une valeur par défaut pour la variable dans la fonction pour éviter un message d’erreur :

Route::get('article/{numero?}', function($numero = null)
{
	if($numero) return "Le numéro de l'article est $numero";
	else return 'Aucun article mentionné !';
});

Les contraintes

On peut contraindre une partie d’une URL à correspondre à un certain type de données avec l’utilisation d’une expression régulière. Voici un exemple :

Route::get('article/{numero}', function($numero)
{
	return "Le numéro de l'article est $numero";
})->where('numero', '[0-9]+');

Ici on oblige le numéro à être un nombre.

Nommer les routes et redirections

Vous pouvez attribuer un nom à une route pour en garder une référence. Voici un exemple :

Route::get('log/{nom?}', array('as' => 'loger', function($nom = null)
{
	if($nom) return $nom;
	else return 'Vous devez vous connecter !';
}));
Route::get('login/{nom?}', function($nom = null)
{
	return Redirect::route('loger', array($nom));
});

J’ai défini deux routes, la première prend en compte un nom de connexion, la seconde n’en prend pas mais elle redirige vers la première. Bon ce n’est pas un exemple très réaliste mais il montre le fonctionnement du système.

Si vous entrez http://localhost/laravel/public/login vous obtenez « Vous devez vous connecter ! » et si vous entrez  http://localhost/laravel/public/login/albert vous obtenez  albert.

Si vous ne nommez pas la route vous pouvez quand même faire une redirection en passant l’URI avec la méthode « to » :

Route::get('log/{nom?}', function($nom = null)
{
	if($nom) return $nom;
	else return 'Vous devez vous connecter !';
});
Route::get('login/{nom?}', function($nom = null)
{
	return Redirect::to('log'.'/'.$nom);
});

La version beta 5 a réintroduit la commande Redirect::home() de Laravel 3 (pour que ça fonctionne il faut que la route correspondante soit nommée home).

Nous verrons d’autres cas de redirection plus tard.

Groupement de routes et préfixage

Il est possible de grouper des routes pour leur appliquer un traitement spécifique, par exemple pour tenir compte d’un préfixe (nous verrons dans un article ultérieur d’autres cas d’application avec un filtrage) :

Route::group(array('prefix' => 'login'), function()
{
	Route::get('', function($nom = null)
	{
		return 'Vous devez vous connecter !';
	});
	Route::get('{nom}', function($nom = null)
	{
		return 'Bienvenu '.$nom;
	});
});

Le groupement de routes se fait avec la méthode Route::group. Ici j’ai aussi défini le préfixe login qui est appliqué à toutes les routes du groupe. Ainsi avec l’URL http://localhost/laravel/public/login on obtient :

Vous devez vous connecter !

Et avec l’URL http://localhost/laravel/public/login/toto on obtient :

Bienvenu toto

Nous verrons d’autres possibilités pour les routes aux cours des articles suivants.

Print Friendly, PDF & Email

39 commentaires

  • abso

    Bonjour,

    merci pour ce tuto 🙂

    j’ai un souci avec les redirections, la méthode « to » fonctionne impec, mais l’autre non,

    pour le code
    Route::get(‘log/{nom?}’, array(‘as’ => ‘log’, function($nom = null)
    {
    if($nom) return $nom;
    else return ‘Vous devez vous connecter !’;
    }));
    Route::get(‘login/{nom?}’, function($nom = null)
    {
    return Redirect::route(‘log’, array($nom));
    });

    sur l’url : http://localhost/laravel/public/log/albert
    j’ai l’erreur suivante:

    ErrorException (E_UNKNOWN)

    log() expects parameter 1 to be double, string given
    Open: C:\wamp\www\laravel\bootstrap\compiled.php

    }
    }
    public function run()
    {
    $parameters = array_filter($this->parameters(), function ($p) {
    return isset($p);
    });
    return call_user_func_array($this->action[‘uses’], $parameters);
    }
    public function matches(Request $request, $includingMethod = true)

    et du coup l’url : http://localhost/laravel/public/log/2.56
    me donne à l’affichage :
    0.94000725849147

    du coup je n’ai pas trop compris et fais mes redirections avec « to ».

    • bestmomo

      Salut,
      Je viens de faire le test et avec la nouvelle version de Laravel il y a effectivement une erreur si l’URL est identique au nom de la route. Je n’ai pas creusé pour savoir ce qui se passe en coulisses. Pour régler ça il suffit de changer le nom de la route. Je vais corriger l’article pour éviter ce bug.

  • John Smith

    Bonsoir Momo,

    Me revoilà encore avec une question. Je cherche à reproduire le moteur de recherche de mon site d’origine que je re-développe en Laravel.
    Je souhaite faire des recherches d’article avec un mot clé mais aussi avec toute une série d’options comme la présente de certains éléments (photos, sons, etc.). Pour mon formulaire et la récupération des options par la méthode post, je n’ai aucun soucis. Le problème c’est dans la transmission des paramètres d’une page à l’autre (car j’affiche l’article sélectionné mais aussi la liste de résultats de la recherche précédente donc j’ai besoin de transmettre les paramètres par la méthode get).
    Avant, j’avais des urls du genre …/index.php?search=true&key=toto&photos=true&son=true&… et je me dis que si je traduit ça sous la forme d’une route du genre …/search/{key}/{photos?}/{son?}/… je ne m’en sortirais pas vue que j’ai des paramètres qui sont en option dans un ordre qui varie. Par exemple si j’ai lancé une recherche d’un article avec du « son » mais pas de « photo » etc. Bref, je ne sais pas si j’ai été clair mais comment fait-on avec les routes quand on a toute une tripotée de paramètres ?
    J’imagine qu’il doit y avoir une astuce mais je manque un peu d’expérience… Je te remercie d’avance si tu peux m’aider.

    A bientôt.

  • John Smith

    Bonjour Momo,

    C’est avec ton tuto que je me décide à me former sur Laravel, aussi je te remercie beaucoup pour ce travail.
    Seulement voilà, je n’arrive pas à faire fonctionner une seule route hormis celle de base c’est à dire le message à la racine me disant que j’ai réussi l’install.

    Je travaille avec Easyphp. Mon site en local est localisé dans un répertoire à part et j’y accède grâce à un alias.
    Alors pour la toute première route, celle du login, j’ai l’adresse : http://127.0.0.1/Laravel/public/login et j’obtiens le message « Objet non trouvé. Error 404. »
    Je ne suis visiblement pas le seul dans ce cas, mais je ne vois pas où sont inscrites les solutions. Peut-être que les gens ont résolu eux-mêmes le problème mais je ne vois pas la solution… Pourrais-tu, s’il te plait essayer de me dépanner. Je te remercie d’avance.

    • John Smith

      Eh bien finalement, je pense avoir trouver une manière de contourner le problème. Plutôt que de créer un alias, j’ai installé le module Virtual Host Manager d’easyphp et j’ai créé un Virtual Host qui pointe vers mon dossier public de laravel. Du coup, il a dû définir tous les droits d’accès qui vont bien et maintenant ça marche…

  • charlie

    Bonjour
    J’obtiens
    URI Action
    GET / Closure
    GET /login Closure
    POST /log Closure
    A la racine, pas de souci je peux faire ce que je veux, travailler avec un return « chaîne » et une vue. Pas de souci. Mais dès que je souhaité créer une route celle-ci n’est pas reconnue.
    En essayant avec index.php/login, même souci (non reconnaissance de l’URI).
    Mais je continue de chercher ..
    Merci pour la réponse très rapide

  • charlie

    Bonjour et avant tout merci pour ce travail titanesque sur Laravel.
    Mon problème porte sur l’écriture la route suivante :
    Route::get(‘login’, function() { return ‘login’; });
    J’obtiens pour http://localhost/laravel/login le message suivant :
    The requested URL /laravel/login was not found on this server.
    Bien sur, j’ai enlever les commentaires sur mod-rewriting et
    décommenté extension=php_openssl.dll
    Y-a-t-il une chose que j’aurai oublié dans public par exemple …
    Merci

  • fmronan

    bonjour
    Tous d’abord merci pour ce tuto qui me fait choisir laravel plutôt qu’un autre framework.
    Je rencontre une erreur quand je teste en « post »
    | and give it the Closure to execute when that URI is requested.
    |
    */

    Route::post(‘log’, function()
    {
    return Input::get(‘nom’);
    });

    Une idée la dessus?

  • AhmedZahraz

    Bonjour,
    J’essaie de tester les routes avec :
    Route::get(‘login’, function()
    {
    return ‘login’;
    });

    mais à chaque fois je reçois l’erreur :
    Objet non trouvé!

    L’URL demandée n’a pas pu être trouvée sur ce serveur. Si vous avez tapé l’URL à la main, veuillez vérifier l’orthographe et réessayer.

    Sachant que la ligne :
    LoadModule rewrite_module modules/mod_rewrite.so
    est décommentée.

    Merci !

    • bestmomo

      Salut !

      D’abord est-ce que tu as bien le message d’accueil de Laravel une fois que tu as tout installé en tapant l’URL de base de ton site ?

      Si c’est le cas quelle est l’URL que tu tapes pour accéder à ton chemin de login ?

  • ljonas6

    Bonjour,
    j’aimerai savoir s’il est possible d’inclure une ancre dans une route?
    J’ai pensé à:
    Route::get(‘ma_route’,function()
    {
    return View::make(‘une_vue#une_div_dans_ma_vue’);
    });
    Mais cela ne marche pas. Y a-t-il une solution?

      • ljonas6

        Merci pour cette solution, je pense etre proche du but mais mon script ne semble pas fonctionner.

        Voici ma route :

        Route::get('allsections/{section}',function($section)
        {
        return View::make('sections.allsections', array('section'=>$section));
        });

        et le script appelé dans la balise de ma vue :



        Ai-je loupé quelque-chose?
        De plus la feuille de style associée à cette vue n’est plus utilisée…

        Merci encore pour votre aide.

  • Frink

    Merci beaucoup pour ce tuto!

    J’ai hésité avec d’autres frameworks pour aborder la question et ce site a fait pencher la balance vers Laravel!

    J’ai ceci dit un souci dès la partie paramètres du chapitre sur les routes:
    Pour le premier exemple (avec http://localhost/laravel/public/article/24), ça fonctionne.
    Mais dès que je teste le code avec le paramètre optionnel (‘article/{numero?}’) et que j’entre comme url http://localhost/laravel/public/article/, j’ai un page not found et suis redirigé vers http://localhost/article

    ‘Nommer les routes et redirections’ génère également des erreurs chez moi.

    J’ai bien activé le mod_rewrite et le reste semble bien tourner (apache, composer).

    Quelqu’un aurait une piste pour moi ? 🙂

    Merci

  • papy2013

    Très bon tuto.
    Petite erreur au chapitre Nommer les routes et redirections
    -> il manque la valeur par défaut de $nom
    Code correct:

    Route::get('login/{nom?}', function($nom = null)
    {
    return Redirect::route('log', array($nom));
    });

    • bestmomo

      Merci d’apprécier mon tuto et merci de me signaler les erreurs, c’est corrigé maintenant ;).

      Il doit y avoir d’autres erreurs dans les articles ultérieurs que j’ai dû remanier plusieurs fois au fil de l’évolution du développement du framework. D’ailleurs pour ce point précis dans la première documentation la valeur par défaut n’était pas mentionnée…

  • padbrest

    … Et sous nos yeux éblouis… Ça marche !!!
    Le bug provient d’un changement assez profond imaginé par Apple dans la dernière version d’OS X Server 10.8 (Mountain Lion pour les intimes 😉
    Pour « simplifier », ils ont mis en place une interface graphique qui n’agit pas directement sur httpd.conf, mais sur un fichier bien caché (il est dans le répertoire /Library/Server/Web/Config/apache2/sites/ et qui s’appelle 0000_any_80_.conf). Il contient une innocente instruction AllowOverride None, tant qu’on n’a pas coché dans l’interface graphique (Serveur > Site web > Sites web du serveur > Modifier les réglages avancés) la case « Autoriser les dérogations à l’aide de fichiers .htaccess ». L’instruction devient alors AllowOverride All.
    Tout ça ne vaut sans doute pas pour la version client d’OS X.
    Merci de m’avoir orienté vers la piste Apache. Laisse peut-être le présent commentaire, il pourrait servir à d’autres : une recherche sur « url rewriting mountain lion server » m’a montré que je n’étais pas le seul à patauger…

  • padbrest

    Et bien ça va te faire quelques jours de tranquillité le temps que je réinstalle 😉
    J’avais pourtant bidouillé peu de choses, c’est du Mac OS X server quasi prêt à l’emploi…
    Merci et à bientôt sur nos écrans 🙂

    • bestmomo

      Non le mystère ne s’épaissit pas, tu sais maintenant que c’est un problème avec Apache :).

      Je suppose que tu es en local, tout dépend de ton système d’exploitation, de ta version d’apache et comment tu l’as installée. Je te conseille là aussi de repartir de zéro et de recréer un serveur tout neuf, des fois on fait plein de bidouilles et on les oublie.

  • padbrest

    Bonjour,
    Merci pour la réponse. J’ai tout réinstallé, et cette fois composer se tient tranquille. Mais du côté de Laravel, pas mieux 🙁
    J’ai même essayé de provoquer volontairement une erreur de syntaxe dans routes.php : j’ai un message « le serveur n’a rien envoyé » en appelant l’adresse /public, mais l’adresse /public/article/234 provoque la même erreur « fichier inexistant », comme si Apache ignorait totalement l’existence de Laravel. Le dossier app/storage/logs est resté vide.
    Je soupçonne un problème de config apache. J’ai testé les deux versions du fichier .htaccess proposées dans http://laravel.com/docs/install, sans succès.
    Une piste ? Je ne voudrais pas polluer trop longuement les commentaires ici, si le pb ne vient pas de Laravel 🙁

    • bestmomo

      Est-ce que tu as bien le module mod_rewrite activé sur ton serveur ? Par exemple si tu entres l’URL …/public/index.php/article/234 est-ce que ça fonctionne ?

      Ne t’en fais pas pour la pollution des commentaires, pour le moment le blog n’est pas saturé et je ferai le ménage au besoin.

  • padbrest

    Bonjour,
    Question du newbie de service 🙂 D’abord bravo pour ce tuto parfaitement clair, c’est assez rare.
    J’ai obtenu le Hello World, mais dès que j’essaie une autre route, rien ne fonctionne, même l’exemple article/{numero}. J’ai seulement le message d’apache qui me dit que le répertoire article n’existe pas.
    Qu’est-ce que j’ai oublié ?
    C’est peut-être sans rapport, mais un essai de mise à jour par composer m’a renvoyé ceci :
    [RuntimeException]
    /Library/Server/Web/…/vendor/nikic/php-parser does not exist and could not be created.
    Merci !

    • bestmomo

      Bonjour,

      D’abord merci pour les encouragements !

      Pour ton souci, si tu as un message d’erreur de composer il faut effectivement commencer par régler ça. Le mieux est de repartir de zéro en allant chercher le pack de base de Laravel qui change souvent. Ensuite lance composer et regarde si tu as toujours le message d’erreur pour le parser PHP. Normalement ça devrait bien se passer.

Laisser un commentaire