X

Laravel 5.0 – Annotations d’itinéraire (supprimées)


Remarque : les annotations de route ont finalement été supprimées du noyau et séparées dans un package géré par la communauté Laravel. Le package doit fonctionner de la même manière que la documentation ici, sauf qu’il nécessite la liaison d’un fournisseur de services personnalisé. Les commentaires peuvent aller aux problèmes Github pour le projet ou à @artisangoose dans le mou Larachat.

Précurseur : PHP Annotations

Si vous ne savez pas comment (ou pourquoi) les annotations existent, je vous suggère de consulter la conférence de Rafael Dohms Annotations PHP : elles existent !. En bref, les annotations sont Remarques à propos de votre code qui vit dans le DocBlock. Mais PHP a la capacité de lire et d’analyser ces notes, et vous pouvez donc les utiliser pour donner des instructions à votre code. Les opinions à leur sujet sont variées, mais ils sont venus à Laravel pour rester.

La mise en scène

L’une des difficultés sur les sites Laravel – en particulier les sites plus grands – est de cartographier mentalement vos routes vers vos méthodes de contrôleur.

Supposons que nous n’utilisons pas les fermetures de route (car ce n’est pas la meilleure pratique et car nous ne pourrons pas profiter de la mise en cache des routes de Laravel 5.0) et nous n’utilisons pas de routes implicites ou de contrôleur de ressources, donc toutes nos routes vont être mappées explicitement à une méthode de contrôleur, quelque part.

Donc, nous avons quelque chose comme ça (notez que Laravel 5.0 préfère $router->get au lieu de Route::get):

// routes.php
$router->get('awesome-sauce/{id}', [
    'as' => 'sauce',
    'uses' => 'AwesomeController@sauce'
]);
<?php namespace App\Http\Controllers;

class AwesomeController {

    public function sauce($id) {}

}

… mais imaginez avoir des dizaines ou des centaines de ces liens. Et si nous pouvions établir un lien plus direct ? Dites, si nous pouvions déterminer l’itinéraire dans le contrôleur? Boum boum boum…

Remarque : Laravel 5.0 utilise POPO (Plain old PHP Objects) pour les contrôleurs au lieu des enfants de la classe \Controller. Plus à ce sujet plus tard.

Présentation des annotations d’itinéraire

OK, c’est clair ce que je veux dire ici. Vérifiez-le:

<?php namespace App\Http\Controllers;

class AwesomeController {

    /**
     * @Get("/awesome-sauce/{id}", as="sauce")
     */
    public function sauce($id) {}

}

… c’est ça.

Un pas de plus. S’ouvrir App/Providers/RouteServiceProvider.phpet ajouter App\Http\Controllers\AwesomeController au $scan déployer:

...
    protected $scan = [
        'App\Http\Controllers\HomeController',
        'App\Http\Controllers\Auth\AuthController',
        'App\Http\Controllers\Auth\PasswordController',
        'App\Http\Controllers\AwesomeController'
    ];

Courir artisan route:scan et il générera automatiquement votre fichier de route à storage/framework/routes.scanned.php. Il y aura beaucoup de routes par défaut, mais voici votre nouvelle route en bas :

<?php
...

$router->get('awesome-sauce/{id}', [
    'uses' => 'App\Http\Controllers\AwesomeController@sauce',
    'as' => 'sauce',
    'middleware' => [],
    'where' => [],
    'domain' => NULL,
]);

Vous déterminez maintenant vos itinéraires en ligne, à l’aide d’annotations, sans toucher routes.php. FAIT.

Deux endroits pour annoter

Notez qu’il y a deux places vous pouvez déterminer vos annotations de route : sur le contrôleur et sur la méthode (ou les deux). Découvrez le contrôleur suivant (issu des tests du framework, mais modifié pour la démonstration) :

<?php namespace App\Http\Controllers;

/**
 * @Resource("foobar/photos", only={"index", "update"}, names={"index": "index.name"})
 * @Controller(domain="{id}.account.com")
 * @Middleware("FooMiddleware")
 * @Middleware("BarMiddleware", except={"update"})
 * @Middleware("BoomMiddleware", only={"index"})
 * @Where({"id": "regex"})
 */
class BasicController {

    /**
     * @Middleware("BazMiddleware")
     * @return Response
     */
    public function index() {}

    /**
     * @return Response
     */
    public function update($id) {}

    /**
     * @Put("/more/{id}", after="log")
     * @Middleware("QuxMiddleware")
     */
    public function doMore($id) {}

}

Notez que certaines annotations sont définies sur le contrôleur et d’autres sur les méthodes. Notez également le nouvel accent mis sur le middleware (et l’absence d’avant et d’après); J’écrirai bientôt un article sur les nouvelles façons dont nous utiliserons le middleware.

Options disponibles

Voici quelques options et cas d’utilisation supplémentaires :

Mappage d’itinéraire de base

Utilisez les verbes que vous avez l’habitude d’utiliser dans votre fichier de routes pour annoter des routes simples.

<?php namespace App\Http\Controllers;

class BasicController {

    /**
     * @Get("awesome")
     */
    public function awesome() {}

    /**
     * @Post("sauce/{id}")
     */
    public function sauce($id) {}

    /**
     * @Put("foo/{id}", as="foo")
     */
    public function foo($id) {}

}

Contrôleurs de ressources

Notez que vous pouvez définir une route de ressource avec @Resource("route-name"); vous pouvez choisir les itinéraires affichés avec only={"method1", "method2"}; et vous pouvez nommer des itinéraires avec names={"method": "name-for-method"}.

<?php namespace App\Http\Controllers;

/**
 * @Resource("foobar/photos", only={"index", "update"}, names={"index": "index.name"})
 */
class FoobarPhotosController
{

    public function index()
    {
        // Index, named as index.name
    }

    public function update()
    {
        // Update, un-named
    }

}

Routage de sous-domaine

Tout comme dans une définition de route normale, les annotations peuvent contrôler le routage de sous-domaine :

<?php namespace App\Http\Controllers;

/**
 * @Controller(domain="{user-name}.my-multi-tenant-site.com")
 */
class MyStuffController
{
    // Do stuff 
}

Intergiciel

Laravel 5.0 remplace les filtres avant et après par un middleware ; revenez bientôt pour un article présentant le fonctionnement de la nouvelle implémentation de Middleware.

<?php namespace App\Http\Controllers;

/**
 * @Middleware("FooMiddleware")
 */
class MiddlewaredController
{

    /**
     * @Middleware("BarMiddleware")
     */
    public function barred() {}

}

Contraintes d’itinéraire

Vous pouvez également appliquer des contraintes d’itinéraire :

<?php namespace App\Http\Controllers;

class RegexedController {

    /**
     * @Where({"id": "regex"})
     */
    public function show($id) {}

}

Numérisation locale

Si votre environnement est détecté comme localLaravel analysera automatiquement vos contrôleurs à chaque page vue. De cette façon, vous n’avez pas à artisan route:scan chaque fois que vous faites un changement.

Routes.php dans Laravel 5

Depuis que j’ai écrit cet article, la valeur par défaut routes.php a été supprimé du projet par défaut. Pour le ramener, éditez App\Providers\RouteServiceProvideret dans le map() méthode, décommentez la ligne qui dit require app_path('Http/routes.php'). Maintenant, vous pouvez simplement créer App/Http/routes.php et utilisez-le comme avant.

Recueil

  • Si vous utilisez routes.php et annotations, les annotations seront répertoriées en premier dans le fichier numérisé.
  • Les guillemets doubles dans les annotations doivent rester doubles. Pas de guillemets simples.

Conclusion

Vous pouvez toujours utiliser routes.php si cela vous met plus à l’aise – ou si vous ne voyez pas la valeur derrière cela.

Une fois de plus, cette nouvelle fonctionnalité de Laravel 5.0 ouvre à la fois de nouvelles possibilités et, dans mon esprit, nous aide également à écrire un code plus propre et mieux architecturé. Étant donné que routes.php est simplement une carte entre les routes d’URL et les contrôleurs, les annotations de route déplacent le mappage dans le contrôleur et suppriment entièrement le besoin d’un fichier de routes séparé.