Laravel 4

Laravel 4 : chapitre 29 : Le routage

Préambule

Nous avons déjà vu le routage dans un article dédié 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 Tongue Out).

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

img29Si tout se passe bien vous devez tomber sur le message d’accueil :

img06

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

img30

Au départ ce fichier contient peu de code :

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 :

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 :

$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…

Les verbes

Laravel reconnait les verbes suivants :

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 un verbe « 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 :

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

É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 :

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 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 :

img31

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

App::missing(function($exception)
{
    return 'Cette page n\'existe pas !';
});

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

Les paramètres

Présentation

Lorsqu’on utilise le verbe get on a bien souvent des paramètres transmis. A 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 :

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 :

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

Paramètre optionnel

Un paramètre variable c’est bien mais des fois 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 :

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 :

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.

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 :

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 :

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 :

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;
});

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 :

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.

Les contrôleurs

Vous effectuerez rarement un traitement au niveau du fichiers 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 :

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 :

<?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 :

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

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 :

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 :

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 :

img43

Bon la mise en page dans ma console n’est pas des plus lisibles mais on distingue 4 routes. Les voici un peu plus 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 2 routes comme on aurait pu s’y attendre mais 4. 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’être accédée avec l’URL de base.

On se rend compte également qu’il y a 5 paramètres optionnels disponibles, ce qui peut être très utile. Ainsi l’URL suivante sera parfaitement digé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 5 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 transmise. En effet puisque toutes les URL qui commencent par l’URL de base sont dirigées 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 :

  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 :

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 :

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 correspondantes :

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 blog, je vais surtout évoquer ici l’aspect routage. Pour créer un contrôleur de ressource il suffit d’utiliser artisan :

img33

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 :

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é ici comment gérer ce genre de contrôleur. Au niveau du routage il suffit d’une simple ligne :

Route::resource('livres', 'LivreController');

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

img42

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 toute autre URL n’est pas dirigée 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 :

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

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 :

img38

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

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

Ce qui vous donne les routes suivantes :

img39

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

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

Voilà maintenant ce que nous obtenons :

img40

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 :

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 :

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

On obtient ces routes :

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

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 :

class TestController extends BaseController {

	public function index($nom)
	{
		return "Coucou $nom";
	}

}

Et une route avec une contrainte :

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

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

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 :

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 moment. On a la possibilité de nommer les routes pour simplifier le code :

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 :

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 :

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 bug. 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ée 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 :

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

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

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 :

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

Et voici les routes :

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 :

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 :

Route::get('infos', array('uses' => 'TestController@index'));

Route::get('test', function()
{
	return Redirect::action('TestController@index')->with('message', 'la chasse');
});

Les méthodes back et refresh

Il arrive fréquemment qu’on doive revenir à l’URL précédente. 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 :

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 :

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 pour avoir la même URL pour la soumission du formulaire et son traitement :

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 :

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 Tongue Out.

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 :

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 :

Route::model('user', 'User', function()
{
    throw new NotFoundException;
});

Quand on l’utilise on tombe sur cette erreur :

img36

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

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

Et il faut aussi informer composer :

"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 :

App::error(function(NotFoundException $exception)
{
	return 'Je ne connais pas cet id !';
});

Maintenant ça fonctionne Smile.

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

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 fil je développerai la question du filtrage qui est évidemment intimement lié au routage Wink.

Print Friendly, PDF & Email

2 commentaires

  • ChDUP

    j’ai du mal à comprendre la distinction entre les routes GET et POST.
    Quand tu présentes les contrôleurs de ressources, on voit ces 2 routes possibles interprétées différemment.
    GET livre et POST livre -> qui vont être orientées respectivement vers les méthodes index et store.
    donc une URL /livre sera interprétée en GET ?
    et la même URL sera interprétée en POST, dans le cas où une variable lui est passée en POST, quelque soit le nom de cette variable ?
    Ai-je bien compris ?
    merci

    • bestmomo

      Salut !
      Désolé pour le retard dans la réponse mais j’avais raté ta question…
      Dans une requête HTTP il n’y a pas que l’URL, il y a aussi tout un tas d’informations, en particulier la méthode utilisée. Si tu veux plus d’informations sur le sujet il y a un tuto bien fait ici.

Laisser un commentaire