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 :
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'); });
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 :
Et 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.
39 commentaires
crisimon
Merci beaucoup pour ce tutoriel, trés clair.
Bravo !
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.
bestmomo
Salut,
J’avais raté ton commentaire, désolé, j’espère que tu as trouvé une solution depuis 😉
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,
ai manipulé mon httpd et remis le # sur le mod_rewrite… allez savoir pourquoi
J’ai réparé et cela fonctionne. Absolument désolé.
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
bestmomo
Et avec :
http://localhost/laravel/public/login
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
bestmomo
Salut,
Est-ce ça fonctionne avec : http://localhost/laravel/index.php/login ?
Regardes ce que tu obtiens avec la commande Artisan :
php artisan routes
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?
fmronan
il manque l’erreur
Symfony \ Component \ Debug \ Exception \ FatalErrorException
syntax error, unexpected ‘Input’ (T_STRING)
fmronan
Trouvé,c’est les copier coller qui pose soucis, je vais donc taper le code,bizarre.
Prestaspirit
Salut,
Pourquoi tu n’utilise pas artisan pour démarrer le site?
bestmomo
Salut,
Je ne suis pas sûr de comprendre ta question…
Prestaspirit
Salut,
Pour démarrer le site ont peut utiliser artisan en tapant la commande suivante :
php artisan serve
le site seras alors accéssible via l’url http://localhost:8000
Comme l’explique Jeffrey Wey dans sont tuto vidéo.
bestmomo
Ah ! Oui je comprends mieux. On a effectivement cette possibilité que je n’ai jamais utilisée. On a des habitudes 🙂 .
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?
bestmomo
Comme solution je vois le passage d’une variable à la vue et un petit bout de javascript qui se lance au chargement de la page et t’envoie sur l’ancre que tu as passée en paramètre.
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.
bestmomo
Pourquoi pas tout simplement :
Frink
Ca tourne très bien sans le slash en effet :-p
merci
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 unpage not found
et suis redirigé vershttp://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
bestmomo
Salut !
Bravo pour avoir choisi Laravel ! C’est un bon choix 🙂
Pour ton souci utilise cette URL :
http://localhost/laravel/public/article
Si tu mets le slash avec rien derrière ta route n’est pas reconnue.
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 🙂
padbrest
En effet ça fonctionne…
Et pourtant httpd.conf contient bien :
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
Le mystère s’épaissit 🙁
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.