IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel pour apprendre à utiliser le framework Laravel 4


précédentsommairesuivant

XXIX. Chapitre 29 : Le routage

XXIX-A. Préambule

Nous avons déjà vu le routage dans un chapitre dédiéChapitre 4 : Les routes et ensuite au fil des exemples. Je vous propose maintenant de revenir sur cet aspect important du framework de façon un peu transversale en envisageant toutes les possibilités qu'il nous offre (enfin je vais tenter d'être exhaustif, je compte sur vous pour me signaler mes oublis Image non disponible).

Pour suivre les exemples, je vous demande de créer un nouvelle installation vierge de Laravel :

Image non disponible

Si tout se passe bien vous devez tomber sur le message d'accueil :

Image non disponible

Vous savez déjà que les routes se trouvent dans le fichier app/routes.php :

Image non disponible

Au départ ce fichier contient peu de code :

 
Sélectionnez
1.
2.
3.
4.
Route::get('/', function()
{
    return View::make('hello');
});

Juste de quoi récupérer l'URL http://localhost/laravel/public et créer la vue de l'accueil. Laravel utilise de façon intensive les appels statiques. C'est une façon de rendre la syntaxe simple et élégante. Comparez le code ci-dessus avec celui-ci :

 
Sélectionnez
app('router')->get('/', function() {
    return app('view')->make('hello');
});

Si vous le testez vous aboutirez au même résultat. Mais avouez que la syntaxe est moins lisible. On peut aussi écrire ce code pour un résultat identique :

 
Sélectionnez
$app['router']->get('/', function() use ($app) {
    return $app['view']->make('hello');
});

Mais le but de ce fil n'étant pas de discuter la question de l'IOC et des façades, on va se contenter d'utiliser la syntaxe la plus élégante…

XXIX-B. Les verbes

Laravel reconnaît les verbes suivants :

 
Sélectionnez
1.
2.
3.
4.
5.
Route::get();
Route::post();
Route::put();
Route::delete();
Route::any();

Les quatre premiers sont classiques et doivent vous parler, peut-être un peu moins le dernier. C'est une expression « passoire » qui accepte tous les autres. Je vous déconseille son utilisation sauf cas très particulier parce qu'a priori vous savez toujours ce qui vous arrive. On peut donc avoir cette syntaxe fonctionnelle pour notre exemple de base :

 
Sélectionnez
1.
2.
3.
4.
Route::any('/', function()
{
    return View::make('hello');
});

XXIX-C. Écriture des routes

On vient de voir la syntaxe élémentaire d'une route, pour laquelle on trouve la description de la route et une fonction anonyme pour effectuer le traitement correspondant. Dans une application on va évidemment se retrouver avec de nombreuses routes. Prenons un exemple simple. Nous voulons répondre aux URL suivants :

Le code correspondant pour les routes est :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Route::get('/', function()
{
    return 'accueil';
});
 
Route::get('login', function()
{
    return 'login';
});
 
Route::get('page/1', function()
{
    return 'page1';
});

Le syntaxe est simple. Pour répondre à la route de base on utilise juste '/', et pour les autres routes on désigne le chemin : 'login' ou 'page/1', celui-ci pouvant être constitué de plusieurs éléments.

Notre exemple fonctionne très bien, mais que se passe-t-il si on entre un URL qui n'a pas été prévu ? Faisons l'essai :

Image non disponible

Évidemment nous recevons un message d'erreur, pour éviter ce désagrément on va ajouter une gestion sommaire de l'erreur 404 :

 
Sélectionnez
1.
2.
3.
4.
App::missing(function($exception)
{
    return 'Cette page n\'existe pas !';
});

Maintenant quel que soit l'URL reçu il sera efficacement traité.

XXIX-D. Les paramètres

XXIX-D-1. Présentation

Lorsqu'on utilise le verbe get on a bien souvent des paramètres transmis. À ce moment-là l'URL a une syntaxe variable et ce qu'on a vu précédemment ne suffit plus pour gérer cette situation. Considérez un exemple simple, vous avez un URL pour des articles qui doit comporter le numéro de l'article de cette forme :

http://localhost/laravel/public/article/1

La syntaxe pour la route dans ce cas est la suivante :

 
Sélectionnez
1.
2.
3.
4.
Route::get('article/{numero}', function($numero)
{
    return 'Article numéro ' . $numero;
});

Vous remarquez que le paramètre variable est placé entre accolades. On prévoit aussi un paramètre pour la fonction anonyme avec le même nom, ce qui permet de disposer ensuite de la valeur correspondante.

On n'est pas limité à un paramètre, on peut par exemple répondre à la situation suivante avec deux paramètres : le premier pour la catégorie des articles et le second pour le numéro :

http://localhost/laravel/public/article/20/1

Dans ce cas le code est le suivant :

 
Sélectionnez
1.
2.
3.
4.
Route::get('article/{categorie}/{numero}', function($categorie, $numero)
{
    return 'Article numéro ' . $numero . ' de la catégorie ' . $categorie;
});

XXIX-D-2. Paramètre optionnel

Un paramètre variable c'est bien, mais parfois on désire également qu'il soit optionnel. Imaginez cette situation : on veut consulter la situation du stock d'articles d'une catégorie complète ou d'un article bien particulier d'une catégorie. En gros donc on veut réagir à ces deux URL :

Dans le premier cas on veut un état du stock pour une catégorie d'articles, et dans le second cas pour un article de cette catégorie. On peut évidemment s'en sortir avec deux routes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::get('stock/{categorie}', function($categorie)
{
    return 'Stock pour la catégorie ' . $categorie;
});
 
Route::get('stock/{categorie}/{article}', function($categorie, $article)
{
    return 'Stock pour l\'article' . $article . ' de la catégorie ' . $categorie;
});

Mais on peut aussi tout regrouper dans une seule en rendant le deuxième paramètre optionnel :

 
Sélectionnez
1.
2.
3.
4.
5.
Route::get('stock/{categorie}/{article?}', function($categorie, $article = null)
{
    if($article) return 'Stock pour l\'article' . $article . ' de la catégorie ' . $categorie;
    else return 'Stock pour la catégorie ' . $categorie;
});

Le fait d'ajouter un point d'interrogation à la fin du nom d'un paramètre le rend optionnel, ce qui est fait ici pour le paramètre article. Il est alors important de prévoir une valeur par défaut, pour le cas où ce paramètre n'est pas renseigné, pour faciliter le codage.

XXIX-D-3. Contraintes sur les paramètres

On veut aussi parfois limiter les valeurs transmises par un paramètre à une certaine plage. Par exemple dans le premier cas précédent on désire uniquement des valeurs numériques. Il est possible de contraindre les valeurs transmises à l'aide d'une expression régulière :

 
Sélectionnez
1.
2.
3.
4.
Route::get('article/{numero}', function($numero)
{
    return 'Article numéro ' . $numero;
})->where('numero', '[0-9]+');

Dans le cas où vous avez besoin de fixer une contrainte sur plusieurs paramètres vous pouvez passer un tableau :

 
Sélectionnez
1.
2.
3.
4.
5.
Route::get('stock/{categorie}/{article?}', function($categorie, $article = null)
{
    if($article) return 'Stock pour l\'article' . $article . ' de la catégorie ' . $categorie;
    else return 'Stock pour la catégorie ' . $categorie;
})->where(array('categorie' => '[0-9]+', 'article' => '[0-9]+'));

Si vous avez une contrainte qui se répète sur plusieurs routes il est possible de définir une expression globale pour simplifier le code. Voici un exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Route::pattern('id', '[0-9]+');
 
Route::get('stock/categorie/{id}', function($id)
{
    return 'Stock pour la catégorie ' . $id;
});
Route::get('stock/article/{id}', function($id)
{
    return 'Stock pour l\'article ' . $id;
});

XXIX-E. Grouper des routes

Lorsqu'on commence à empiler les routes c'est bien de pouvoir un peu les classer. il est possible de regrouper des routes à partir d'un préfixe identique. Voici un exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Route::group(array('prefix' => 'categorie'), function()
{
    Route::get('stock/{id}', function($id)
    {
        return "Stock de la catégorie $id";
    });
    Route::get('{id_categorie}/{id_article}', function($id_categorie, $id_article)
    {
        return "Article numéro $id_article de la catégorie $id_categorie";
    });
});

Ces routes vont intercepter ces deux types d'URL :

La factorisation du terme « categorie » permet de regrouper les deux routes.

XXIX-F. Les contrôleurs

Vous effectuerez rarement un traitement au niveau du fichier des routes. Vous préférerez organiser votre code dans des contrôleurs. Il faut donc pouvoir au niveau des routes pointer sur des méthodes de contrôleurs. Dans votre installation de base de Laravel vous avez un contrôleur HomeController avec une seule méthode showWelcome. Voyons comment diriger une route sur cette méthode :

 
Sélectionnez
Route::get('/', 'HomeController@showWelcome');

Si maintenant vous utilisez l'URL http://localhost/laravel/public vous tombez sur la page d'accueil.

La syntaxe est simple : le nom du contrôleur et celui de sa méthode séparés par l'arobase.

Évidemment si vous avez placé vos contrôleurs dans un espace de nom particulier il faut le signaler. Voici par exemple le contrôleur HomeController maintenant placé dans un espace de nom :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<?php
namespace ChezMoi;
use BaseController;
use View;
class HomeController extends BaseController {
 
    public function showWelcome()
    {
        return View::make('hello');
    }
 
}

Pour pointer ce contrôleur il faut signaler l'espace de nom au niveau de la route :

 
Sélectionnez
Route::get('/', 'ChezMoi\HomeController@showWelcome');

XXIX-F-1. Les contrôleurs RESTful

Un gros avantage de l'utilisation de contrôleurs c'est qu'on peut énormément simplifier le routage en l'automatisant. On peut ainsi créer un contrôleur RESTful, voici un exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
class ArticleController extends BaseController {
 
  public function getIndex()
  {
    echo Form::open(array('url' => 'article/ajout'));
    echo Form::label('nom', 'Entrez le nom : ');
    echo Form::text('nom');
    echo Form::submit('Envoyer');
    echo Form::close();
  }
 
  public function postAjout()
  {
      return 'Le nom ' . Input::get('nom') .  ' a été entré.';
  }
 
}

Ce contrôleur comporte deux méthodes : la première pour afficher un formulaire de saisie, la seconde pour recevoir la soumission du formulaire. Évidemment cet exemple est volontairement minimaliste pour se concentrer sur le routage. Ce qu'il faut remarquer, c'est la syntaxe des noms de méthodes qui suivent la convention de nommage REST. Ces noms sont composés du verbe à utiliser suivi d'un nom. Il faut combiner cela à la définition d'une route pour que ça fonctionne :

 
Sélectionnez
Route::controller('article', 'ArticleController');

Maintenant la méthode getIndex du contrôleur correspond à l'URL http://localhost/laravel/public/article/index et le verbe correspondant est get. De la même façon la méthode postAjout correspond à l'URL http://localhost/laravel/public/article/ajout avec le verbe post. Vous voyez que le routage devient extrêmement simple à réaliser.

Il est intéressant de savoir quelles sont les routes vraiment générées, pour cela on peut utiliser la commande routes d'Artisan :

Image non disponible

Bon, la mise en page dans ma console n'est pas des plus lisibles mais on distingue quatre routes. Les voici un peu plus clairement exposées :

URI

Action

GET article/index/{one?}/{two?}/{three?}/{four?}/{five?}

ArticleController@getIndex

GET article

ArticleController@getIndex

POST article/ajout/{one?}/{two?}/{three?}/{four?}/{five?}

ArticleController@postAjout

GET article/{_missing}

ArticleController@missingMethod

On trouve non pas deux routes comme on aurait pu s'y attendre mais quatre. On se rend compte qu'on peut accéder à la méthode getIndex avec ces deux URL :

C'est une caractéristique de cette méthode d'offrir la possibilité d'y accéder avec l'URL de base.

On se rend compte également qu'il y a cinq paramètres optionnels disponibles, ce qui peut être très utile. Ainsi l'URL suivant sera parfaitement générée sans erreur :

http://localhost/laravel/public/article/index/1/1/1/1/1

Par contre ces paramètres ne sont évidemment pas disponibles avec l'URL de base. On trouve la même possibilité pour la méthode postAjout. En fait ces cinq paramètres optionnels sont générés pour toutes les méthodes. Il faut le savoir.

La dernière route concerne les méthodes manquantes. L'URL de base pointe bien sur le contrôleur, mais aucune méthode ne correspond à l'URI transmis. En effet puisque tous les URL qui commencent par l'URL de base sont dirigés sur le contrôleur, si la méthode associée est manquante on tombe sur une erreur. On doit donc ajouter cette méthode à notre contrôleur :

 
Sélectionnez
1.
2.
3.
4.
public function missingMethod($parameters = array())
  {
      return var_dump($parameters);
  }

Ici j'ai juste mis en évidence le contenu du paramètre $parameters. Ainsi si on utilise par exemple l'URL http://localhost/laravel/public/article/un/deux/trois, on obtient un tableau avec les paramètres de la requête :

 
Sélectionnez
array(3) { [0]=> string(2) "un" [1]=> string(4) "deux" [2]=> string(5) "trois" }

Pour illustrer ces éléments voici un exemple d'utilisation d'un paramètre optionnel :

 
Sélectionnez
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.
class ArticleController extends BaseController {
 
  public function getSaisieArticle($type = 0)
  {
    echo Form::open(array('url' => 'article/ajout'));
    echo Form::label('nom', 'Entrez le nom : ');
    echo Form::text('nom');
    if($type == 1) {
        echo '<br>', Form::label('poids', 'Entrez le poids : ');
    echo Form::text('poids');       
    }
    echo '<br>', Form::submit('Envoyer');
    echo Form::close();
  }
 
  public function postAjout()
  {
    $reponse = 'Le nom ' . Input::get('nom') .  ' a été entré.';
    if (Input::has('poids')) $reponse .= '<br>' . 'Le poids ' . Input::get('poids') .  ' a été entré.';
    return $reponse;
  }
 
  public function missingMethod($parameters = array())
    {
      return 'Je ne reconnais pas cette demande !';
    }
 
}

Si le paramètre est présent et égal à 1, alors on ajoute un contrôle au formulaire. J'ai aussi montré la possibilité de constituer le nom d'une méthode de plusieurs mots. Il faut en tenir compte dans l'URL. Voici les deux URL correspondants :

XXIX-G. Les contrôleurs de ressources

Les contrôleurs RESTful sont intéressants, mais les contrôleurs de ressource le sont encore plus si on a une situation adaptée à leur usage ! J'ai déjà évoqué plusieurs fois cette possibilité dans ce tutoriel, je vais donc surtout évoquer ici l'aspect routage. Pour créer un contrôleur de ressource il suffit d'utiliser Artisan :

Image non disponible

Ici j'ai demandé la création d'un contrôleur pour la gestion de livres. Cette simple action a créé le contrôleur avec toutes ses méthodes :

 
Sélectionnez
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.
class LivreController extends \BaseController {
 
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        //
    }
 
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        //
    }
 
    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        //
    }
 
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        //
    }
 
    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function edit($id)
    {
        //
    }
 
    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        //
    }
 
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function destroy($id)
    {
        //
    }
 
}

J'ai déjà montré iciChapitre 22 : Installer des générateurs comment gérer ce genre de contrôleur. Au niveau du routage il suffit d'une simple ligne :

 
Sélectionnez
Route::resource('livres', 'LivreController');

Petite action gros effet ! Voici ce que nous obtenons comme routes :

Image non disponible

Cette fois c'est un peu plus lisible… On dispose ainsi de toutes les routes utiles pour gérer du contenu. Parfois on a des particularités qui obligent à ajouter quelques routes, mais pour des situations simples c'est tout à fait adapté et surtout très élégant au niveau du code.

Cette fois nous n'avons pas besoin de gérer les méthodes absentes :en effet étant donné que les méthodes sont standardisées tout autre URL n'est pas dirigé vers le contrôleur, et vous pouvez gérer ça tranquillement au niveau des routes.

Remarquez que chaque route possède par défaut un nom. Si ces noms ne vous conviennent pas vous avez la possibilité de les changer. Par exemple vous n'aimez pas le nom livres.show et vous lui préférez livres.voir. Voici le code correspondant :

 
Sélectionnez
Route::resource('livres', 'LivreController',
   array('names' => array('show' => 'livres.voir'));

XXIX-H. Ressources imbriquées

Une possibilité pas trop connue concernant les contrôleurs de ressources est celle qui consiste à les imbriquer. Comme un exemple vaut toujours mieux qu'un long discours, imaginez que vous avez des articles rangés dans des catégories. Vous créez un contrôleur de ressource pour ces deux éléments :

Image non disponible

Vous créez ainsi les deux contrôleurs. Si vous agissez de façon classique vous créez aussi ces deux routes :

 
Sélectionnez
Route::resource('categorie', 'CategorieController');
Route::resource('article', 'ArticleController');

Ce qui vous donne les routes suivantes :

Image non disponible

Vous pouvez difficilement avec ces routes gérer par exemple un URL du genre http://localhost/laravel/public/categorie/8/article/5, ce qui serait pourtant bien pratique ! Pour y parvenir on va faire une petite modification dans nos routes :

 
Sélectionnez
Route::resource('categorie', 'CategorieController');
Route::resource('categorie.article', 'ArticleController');

Voilà maintenant ce que nous obtenons :

Image non disponible

Maintenant les routes sont bien plus intéressantes ! Par exemple pour l'URL considérée ci-dessus on trouve la route GET categorie/{categorie}/article/{article}. Pour la gérer au niveau du contrôleur des articles, il faut évidemment tenir compte du fait qu'on a deux paramètres transmis alors que le générateur n'en a évidemment prévu qu'un seul. Donc par exemple on peut avoir :

 
Sélectionnez
1.
2.
3.
4.
public function show($id_categorie, $id_article)
{
    return "Voir l'article d'id $id_article de la catégorie $id_categorie";
}

Étant donné qu'il y a deux paramètres transmis dans l'URL, on prévoit deux paramètres dans la méthode du contrôleur. Il faut faire la même chose pour les méthodes edit, update et destroy si vous les utilisez.

Vous n'êtes pas limités à un niveau d'imbrication. Par exemple avec ces déclarations :

 
Sélectionnez
Route::resource('categorie', 'CategorieController');
Route::resource('categorie.article', 'ArticleController');
Route::resource('categorie.article.composant', 'ComposantController');

On obtient ces routes :

Image non disponible

Dans ce cas pour le contrôleur des composants vous aurez évidemment trois paramètres pour les méthodes concernées.

XXIX-I. Contrainte pour les contrôleurs

On a vu qu'il est possible de contraindre les valeurs des paramètres d'une route avec une expression régulière. Est-il possible d'effectuer ce filtrage aussi quand on pointe sur un contrôleur ? A priori oui, mais faisons quand même l'essai. créons pour cela un petit contrôleur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
class TestController extends BaseController {
 
    public function index($nom)
    {
        return "Coucou $nom";
    }
 
}

Et une route avec une contrainte :

 
Sélectionnez
Route::get('/{nom}', 'TestController@index')->where('nom', '[a-z]+');;

Si vous testez ce code, vous verrez que ça fonctionne très bien.

XXIX-J. Redirections et routes nommées

On reçoit des URL du client, mais il arrive aussi souvent qu'on doive effectuer une redirection dans notre code. Là aussi Laravel propose une syntaxe élégante. Il suffit d'utiliser Redirect :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::get('/', function()
{
    return 'Accueil';
});
 
Route::get('/test', function()
{
    return Redirect::to('/');
});

Ici l'URL http://localhost/laravel/public/test renvoie à la première route. Même si cette syntaxe est pratique elle peut devenir lourde par moments. On a la possibilité de nommer les routes pour simplifier le code :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::get('/', array('as' => 'accueil', function()
{
    return 'Accueil';
}));
 
Route::get('/test', function()
{
    return Redirect::route('accueil');
});

Il existe une méthode spéciale si la route se nomme home :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::get('/', array('as' => 'home', function()
{
    return 'Accueil';
}));
 
Route::get('/test', function()
{
    return Redirect::home();
});

Mais c'est un peu anecdotique surtout pour nous qui parlons français. Par contre il peut être très utile de transmettre des paramètres lors de la redirection :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::get('test', function()
{
    return Redirect::route('accueil', array('Alfred'));
});
 
Route::get('{nom?}', array('as' => 'accueil', function($nom = 'inconnu')
{
    return "Bonjour $nom";
}));

J'en profite pour signaler une chose importante concernant les routes, qui parfois peut faire chercher des heures un bogue. Les routes sont analysées dans l'ordre et dès que l'une d'entre elles correspond à l'URL on ne va pas plus loin. Ici le fait d'inverser les deux routes rendrait le code inopérant parce que l'URL http://localhost/laravel/public/test serait intercepté par la première route avec le message « Bonjour test ».

Le nommage peut aussi s'effectuer pour une route qui pointe une méthode de contrôleur, de même qu'il est possible de rediriger vers un contrôleur. Considérons un contrôleur basique :

 
Sélectionnez
class TestController extends BaseController {
    public function index(){return "Informations";}
}

Et maintenant prévoyons une route nommée et deux redirections possibles avec deux syntaxes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Route::get('infos', array(
    'as' => 'informations', 
    'uses' => 'TestController@index'
));
 
Route::get('test1', function()
{
    return Redirect::action('TestController@index');
});
 
Route::get('test2', function()
{
    return Redirect::route('informations');
});

Il est aussi possible de passer des paramètres pour une redirection vers un contrôleur. Ajoutons un paramètre à notre contrôleur d'exemple :

 
Sélectionnez
class TestController extends BaseController {
    public function index($sujet)   {   return "Informations sur $sujet";   }
}

Et voici les routes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Route::get('infos/{sujet}', array(
    'as' => 'informations', 
    'uses' => 'TestController@index'
));
 
Route::get('test1', function()
{
    return Redirect::action('TestController@index', array('sujet' => 'la course'));
});
 
Route::get('test2', function()
{
    return Redirect::route('informations', array('la chasse'));
});

Remarquez les deux syntaxes pour transmettre le paramètre. L'utilisation de paramètres nommés se justifie s'il y en a plusieurs à transmettre.

On peut aussi transmettre des informations par la session. Modifions le contrôleur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
class TestController extends BaseController {
    public function index() {
        if (Session::has('message'))    return "Informations sur " . Session::get('message');
        else return "Pas d'information";
    }
}

Et les routes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
Route::get('infos', array('uses' => 'TestController@index'));
 
Route::get('test', function()
{
    return Redirect::action('TestController@index')->with('message', 'la chasse');
});

XXIX-K. Les méthodes back et refresh

Il arrive fréquemment qu'on doive revenir à l'URL précédent. Dans ce cas il est évidemment possible de désigner explicitement la route mais on peut également utiliser la méthode bien pratique back. Voici un exemple élémentaire de scénario avec un formulaire pour entrer un nom, une validation, et un retour au formulaire, avec affichage d'une information en cas d'erreur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Route::get('/', function()
{
    if(Session::has('info')) echo 'Vous avez fait une erreur de saisie !', '<br>';
    echo Form::open(array('url' => 'ajout'));
    echo Form::label('nom', 'Entrez le nom : ');
    echo Form::text('nom');
    echo Form::submit('Envoyer');
    echo Form::close();
});
 
Route::post('ajout', array('before' => 'csrf', function()
{
    $validator = Validator::make(Input::all(), array('nom' => 'required|min:5'));
    if ($validator->fails()) return Redirect::back()->with('info', 'Erreur !');
    else return 'Coucou ' . Input::get('nom'); 
}));

La ligne intéressante est celle qui concerne la redirection :

 
Sélectionnez
if ($validator->fails()) return Redirect::back()->with('info', 'Erreur !');

Avec cette méthode on revient naturellement afficher le formulaire en cas d'erreur de saisie.

Voyons maintenant une autre approche avec ce code, en apportant un petit changement afin d'avoir le même URL pour la soumission du formulaire et son traitement :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Route::get('ajout', function()
{
    if(Session::has('info')) echo 'Vous avez fait une erreur de saisie !', '<br>';
    echo Form::open(array('url' => 'ajout'));
    echo Form::label('nom', 'Entrez le nom : ');
    echo Form::text('nom');
    echo Form::submit('Envoyer');
    echo Form::close();
});
 
Route::post('ajout', array('before' => 'csrf', function()
{
    $validator = Validator::make(Input::all(), array('nom' => 'required|min:5'));
    if ($validator->fails()) return Redirect::refresh()->with('info', 'Erreur !');
    else return 'Coucou ' . Input::get('nom'); 
}));

Le fonctionnement est le même, mais on a juste l'URL http://localhost/laravel/public/ajout avec le verbe « get » à la présentation du formulaire, et « post » à la soumission. Cette fois j'ai utilisé la méthode refresh pour rediriger sur le même URL en cas d'erreur :

 
Sélectionnez
if ($validator->fails()) return Redirect::refresh()->with('info', 'Erreur !');

J'aurais évidemment pu encore utiliser back, mais il fallait bien que je trouve un cas pour refresh qui est quand même d'une utilisation moins courante Image non disponible.

XXIX-L. Injection d'un modèle

Si vous avez besoin d'informations issues d'une base données et que vous utilisez Eloquent, vous pouvez injecter un modèle dans une vue. Par défaut vous avez le modèle User dans l'installation de base de Laravel. Il suffit de créer une base et d'ajouter des enregistrements pour tester ça. Ensuite le codage est simple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
Route::model('user', 'User');
 
Route::get('{user}', function(User $user)
{
    return $user->username;
});

Avec l'URL http://localhost/laravel/public/1 on récupère l'enregistrement qui a l'ID 1 comme paramètre de la fonction anonyme de la route. On peut ensuite utiliser ce paramètre comme on veut. ici je me contente d'afficher le nom de l'utilisateur.

Que se passe-t-il si cet ID ne correspond à aucun enregistrement ? La route est alors ignorée et on se retrouve avec une erreur 404 qu'il suffit de gérer comme les autres. Si ce comportement ne vous convient pas, il est possible de gérer spécifiquement l'erreur. C'est ce qui est indiqué dans la documentation avec ce code :

 
Sélectionnez
1.
2.
3.
4.
Route::model('user', 'User', function()
{
    throw new NotFoundException;
});

Quand on l'utilise, on tombe sur cette erreur :

Image non disponible

On dirait que cette classe NotFoundException n'est pas très connue Image non disponible. Bon on va arranger ça. Il faut déclarer cette classe, par exemple dans un fichier app/exception.php :

 
Sélectionnez
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class NotFoundException extends NotFoundHttpException {}

Et il faut aussi informer Composer :

 
Sélectionnez
"classmap": [
   "app/exceptions.php",
   "app/commands",

Et faire un petit coup de dumpautoload. Ensuite on écrit le code pour gérer cette exception, le mieux étant dans le fichier app/start/global.php :

 
Sélectionnez
1.
2.
3.
4.
App::error(function(NotFoundException $exception)
{
    return 'Je ne connais pas cet id !';
});

Maintenant ça fonctionne Image non disponible.

Une dernière possibilité est de créer une requête spécifique :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::bind('user', function($id, $route)
{
    return User::find($id);
});
 
Route::get('{user}', function(User $user)
{
    return $user->username;
});

Bon là je me suis contenté de trouver l'utilisateur avec l'ID passé. Mais sur ce principe on peut concevoir des recherches élaborées.

Dans un prochain chapitre je développerai la question du filtrage qui est évidemment intimement lié au routage Image non disponible.


précédentsommairesuivant

Copyright © 2017 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.