Newsletter Apprendre Laravel #8

Envoyée le 09 avril 2019

Listeners et Policies Auto-discovery

Une des nouveautés de la version 5.8 de Laravel et l'auto-découverte des policies. Plus besoin de renseigner quelle policy est associée à quel modèle Eloquent, le framework va automatiquement déterminer le nom de la policy via le nom du modèle. Si vous souhaitez en savoir plus sur ce point, j'ai publié une vidéo sur ma chaîne YouTube à ce sujet : https://youtu.be/mZVwC5NqAkY

Plus récemment, dans la version 5.8.9, Taylor a également ajouté l'auto-découverte des listeners des évènements. Comment cela fonctionne-t-il ? À chaque requête, le framework va parcourir tous les listeners situés dans le dossier app/Listeners et inspecter la méthode handle() de ces classes.

class SendInvoice
{
    public function handle(InvoiceWasGenerated $event)
    {
        //
    }
}

En PHP il est possible d'utiliser l'API de réflection afin d'obtenir des informations sur les méthodes. Grace au type pu premier paramètre de la fonction handle(), Laravel est donc capable de déterminer que le listener SendInvoice doit être appelé lorsque l'évènement InvoiceWasGenerated est émis.

Trois choses sont tout de même à noter.

Premièrement, on remarque que ce n'est pas la même approche que pour les policies. Elles sont déterminées en transformant le nom du modèle App\Invoice en nom de la policy App\Policies\InvoicePolicy sans utiliser l'API de réflection de PHP. Pourquoi ? Parce que, contrairement aux policies, le nom des listeners n'est pas lié directement aux noms des évènements. Si vous nommez vos listeners selon l'évènement écouté, vous ne pouvez avoir qu'un seul listener par évènement et vous perdez tout l'avantage du découplage du système d'évènements. Inversement, il devrait normalement être possible pour un listener de réagir de la même façon à deux évènements différents. Il est intéressant de noter que Laravel ne permet pas ce scénario avec l'auto-découverte (il est toujours possible de le faire en enregistrant les listeners manuellement).

Deuxièmement, cette solution est lente. La réflection en PHP n'est pas une opération rapide, et cette opération doit être effectuée pour tous les listeners, à chaque requête. Plus le nombre de listeners de l'application est grand, plus le système va prendre du temps. C'est pour ça que Taylor à mis en place un système de cache avec php artisan event:cache. Cette commande est à lancer lors de la mise en production. L'auto-découverte ne sera alors exécutée qu'une seule fois et le résultat sera stocké dans un fichier pour les futures requêtes.

Enfin, on remarque que cette nouveauté assez impactante (lors de la mise à jour, il se pourrait que des listeners non voulus soient appelé alors que ce n'était pas prévu) a été réalisée lors d'une mise à jour mineure. Pour ne pas perturber les applications existantes mais pour quand même obtenir des retours sur la fonctionnalité, l'auto-découverte des listeners a été placé derrière ce que l'on appelle un « feature flag ». Pour bénéficier de la fonctionnalité, vous devez l'activer via la méthode shouldDiscoverEvents de votre EventServiceProvider. Cette méthode retourne false par défaut. Sachez quand même que cette fonctionnalité sera sans doute activée par défaut en Laravel 5.9.

Système de versionnement de Laravel

Laravel n'utilise pas le système standard du Semantic Versioning. À la place il utilise un système paradigm.major.minor. Les versions mineures peuvent avoir lieu toutes les semaines (généralement le mardi, même si ce n'est pas une règle absolue) et ne contiennent pas de breaking changes. Les versions majeures ont lieu tous les 6 mois (généralement après la Laracon Online en février/mars et après la Laracon EU début septembre) et contiennent des breaking changes. Et enfin les changements de paradigme qui sont des changements majeurs sur le fonctionnement du framework.

Ce système a été choisi afin de permettre au framework d'évoluer très rapidement et de répondre aux besoins en ajoutant de nouvelles fonctionnalités très rapidement (sans attendre 6 mois). De plus, les breaking changes peuvent être faits rapidement en cas de nécessité sans exploser la numérotation (ReactJS est en version 16.8.6 par exemple).

Le framework étant stable, il n'y a plus trop de raison de faire des changements cassant la compatibilité et encore moins de faire de changements de paradigmes majeurs. Un changement de paradigme évoqué pourrait être le passage au Semantic Versionning par exemple avec Laravel 6.

"Convention over configuration"

Avec ces récentes mises à jour, Laravel prouve à nouveau qu'il s'appuie de plus en plus sur les conventions en remplacement de la configuration. L'objectif est que, si le développeur respecte les conventions de Laravel (listeners dans app/Listeners, policies dans app/Policies…), la configuration n'est pas nécessaire et tout est automatiquement découvert par le framework.

C'est un point très agréable pour commencer rapidement avec Laravel, mais qui montre également rapidement ses limites dans le cas d'un projet un peu plus important. Par exemple, je n'imaginerais pas mettre tous mes modèles dans le dossier app, je préfère les séparer dans des dossiers métiers plus parlants. Dans ce cas, les conventions ne fonctionnent plus automatiquement, mais il est toujours possible de les reconfigurer pour qu'elles s'adaptent à nos choix.

J'espère que cette nouvelle newsletter aura été intéressante pour vous. Si vous souhaitez en savoir plus sur les nouveautés de Laravel 5.8, j'ai publié trois vidéos sur YouTube : « Relations HasOne, HasMany et HasOneThrough », « Model policies et permissions » et « Cache et PSR » où je parcours les nouveautés.

Bonne semaine à tous,

Thibaud