API Platform (beta) : le framework web PHP nouvelle génération

Les-Tilleuls.coop est fière d’avoir participé au développement de API Platform et continue aujourd’hui de lui apporter tout son soutien en qualité de sponsor et de principal contributeur.

Pour les adeptes de la langue de Shakespeare, cet article est disponible en version anglaise. Dans l'optique d'un meilleur confort de lecture, sa traduction française vous sera présentée en trois parties. Commençons dès à présent avec la première !

En juin dernier, PHP célébrait ses 20 ans. En 20 ans, le Web a changé radicalement et il évolue à présent plus rapidement que jamais :

PHP.net, Symfony, Facebook et bien d’autres ont travaillé dur pour améliorer l’écosystème PHP et le professionnaliser. L’univers PHP a comblé l’écart avec la plupart des solutions backend et s’avère souvent plus novateur qu’elles.

Mais dans les domaines critiques que nous avons précédemment décrits, de nombreux éléments peuvent être améliorés. Presque toutes les solutions existantes sont conçues et documentées pour créer des sites internet “à l’ancienne” : un serveur génère puis envoie de bons vieux documents HTML aux navigateurs.

Quel plus beau cadeau pour l’anniversaire de PHP qu’un tout nouvel ensemble d’outils pour démarrer des projets web modernes ? Voici donc API Platform, un framework pour les projets API-first construit sur Symfony ! Tout comme pour les autres frameworks modernes tels que Zend et Symfony, il s’agit à la fois d’un framework complet tout-en-un et d’un ensemble de composants PHP indépendants ainsi que de bundles pouvant être utilisés séparément.

Face à l’architecture promue par le framework, nombre d’entre vous seront se méfieront mais lisez cet article jusqu’à la fin et vous verrez comment le développement moderne devient de nouveau simple et amusant avec API Platform :

  • Commencez par créer une API REST hypermédia exposant des données structurées qui peuvent être comprises par n’importe quel client compatible, comme vos applications ou les moteurs de recherche (JSON-LD avec le vocabulaire Schema.org). Cette API est le point d’entrée central et unique pour accéder aux données et les modifier. Elle contient également toute la logique métier.
  • Ensuite, créez autant de clients que vous le souhaitez en utilisant vos technologies frontend préférées : une application web HTML5/Javascript interrogeant l’API en AJAX (bien entendu) mais aussi une application iOS ou Android native ou encore une application de bureau. Les clients n’exposent que les données et les formulaires.

Voyons maintenant comment s’y prendre. Dans ce tutoriel, nous allons créer une application de blog typique avec API Platform.

Si vous êtes pressé, une démo est disponible en ligne et toutes les sources créées dans ce tutoriel sont accessibles sur GitHub :

Pour créer le composant API de votre projet, nous allons :

  • Bootstraper un modèle de données complet et fonctionnel incluant le mapping objet-relationnel, les règles de validation et les métadonnées sémantiques avec le générateur fourni par API Platform (vous pouvez bien entendu également fabriquer vous-même votre modèle de données ou modifier celui qui a été généré afin de l’adapter à vos besoins).
  • Exposer ce modèle de données à travers une API read/write (CRUD) suivant les normes ouvertes JSON-LD et Hydra Core Vocabulary, avec des métadonnées Schema.org et pléthore de fonctionnalités prêtes à l’emploi : pagination, validation, sérialisation des erreurs, filtres et de nombreuses autres fonctionnalités (ici aussi, tout est extensible grâce à un système d’événements puissant et une programmation fortement orientée objet).

Ensuite, nous allons développer une petite application web AngularJS pour montrer comment créer et consommer des données depuis l’API. Gardez bien à l’esprit que vous pouvez utiliser la technologie côté client que vous préférez (testé et approuvé avec Angular, React, Ionic, Swift, mais peut fonctionner avec n’importe quel langage capable d’envoyer des requêtes HTTP).

Prérequis

Seul PHP 5.5+ doit être installé pour exécuter API Platform. Le framework est livré avec un serveur web intégré pour l’environnement de développement.

Pour suivre ce tutoriel, une base de données doit être installée (mais elle n’est en rien obligatoire pour utiliser le framework). Nous recommandons MySQL ou MariaDB mais d’autres gestionnaires de données comme SQLite, PostgreSQL, Oracle et SQL serveur sont supportés par Doctrine.

Installer le framework

Commençons notre nouveau projet d’API pour le blog. La manière la plus simple de créer un nouveau projet est d’utiliser Composer (il doit être installé sur votre machine) :

composer create-project dunglas/api-platform --stability=beta blog-api

Composer crée le squelette de la nouvelle API de blog puis récupère le framework et toutes ses dépendances.

A la fin de l’installation, des paramètres de configuration comme les identifiants de base de données vous seront demandés. Tous les paramètres de configuration peuvent être modifiés ultérieurement en éditant le fichier app/config/parameters.yml.

Le framework API Platform est préconfiguré pour utiliser la très populaire bibliothèque Doctrine ORM. Elle est supportée nativement par tous les composants d’API Platform. Cependant, l’ORM Doctrine est pleinement facultatif : vous pouvez la remplacer par votre ORM favori ou choisir de ne pas utiliser d’ORM du tout ni de base de donnée.

L’installeur vous demandera :

  • les identifiants du serveur de messagerie (pour envoyer des e-mails) ;
  • l’emplacement de l’application ;
  • l’URL de votre application web client par défaut pour régler automatiquement les entêtes CORS appropriés, réglez-la sur http://locahost:9000 (l’URL par défaut du serveur Grunt intégré) pour suivre ce tutoriel ;
  • un nom et une description de l’API qui seront utilisés dans la documentation générée ;
  • un jeton secret (choisissez-en un long) pour les fonctions cryptographiques.

Jetez un oeil au contenu du répertoire généré. Vous devriez reconnaître la structure d’un répertoire d’application Symfony. C’est normal : le squelette généré est une application Symfony complète parfaitement valable qui respecte les bonnes pratiques Symfony. Cela signifie que vous pouvez :

Le squelette est fourni avec des fichiers de démonstration. Supprimez-les :

  • videz app/config/schema.yml et app/config/services.yml ;
  • supprimez tous les fichiers dans le répertoire src/AppBundle/Entity/.

Générer le modèle de données

Le premier outil très utile fourni par API Platform est son générateur de modèle de données également connu sous le nom de PHP Schema. Ce composant d’API Platform peut aussi être utilisé de façon autonome pour bootstraper n’importe quel modèle de données PHP.

Pour démarrer notre modèle de données de blog, nous allons parcourir Schema.org et trouver un schéma existant qui décrit parfaitement ce que nous désirons : https://schema.org/BlogPosting.

L’outil de ligne de commande schema va générer instantanément un modèle de données PHP depuis le vocabulaire Schema.org :

Parcourez Schema.org, choisissez les types et les propriétés dont vous avez besoin (de nombreux schémas sont disponibles) et exécutez notre générateur de code. Et voilà ! Vous obtenez un modèle de données PHP complet incluant :

  • un ensemble d’entités PHP avec propriétés, constantes (valeurs enum), getters, setters, adders et removers. La hiérarchie de classes fournie par Schema.org sera convertie en hiérarchie de classes PHP avec des classes parentes abstraites. Le code généré est conforme aux normes de codage PSR ;
  • une PHPDoc complète et de haute qualité pour les classes, les propriétés, les constantes et les méthodes extraites de Schema.org ;
  • les  annotations de mapping Doctrine ORM incluant des colonnes de base de données avec types, relations, cardinalités et héritage de classe (à travers l’annotation @AbstractSuperclass) ;
  • la validation des données avec les annotations Symfony Validator incluant la validation du type de données, le support enum (choix) et la vérification des propriétés requises ;
  • les interfaces et le support du Doctrine ResolveTargetEntityListener ;
  • une liste de valeurs fournies par Schema.org avec des classes PHP Enum.

Le fait de réutiliser un schéma sémantique préexistant présente de nombreux avantages :

Ne réinventez pas la roue

Les modèles de données fournis par Schema.org sont populaires et ont prouvé leur efficacité. Ils couvrent un large éventail de sujets, y compris les travaux créatifs, le e-commerce, les événements, la médecine, les réseaux sociaux, les gens, l’adresse postale, l’organisation, le lieu ou les critiques. Schema.org tire ses origines d’un grand nombre de vocabulaires préexistants bien construits et est utilisé avec succès par de plus en plus de sites web et d’applications.

Prenez les schémas applicables à votre application, générez votre modèle PHP puis customisez et spécialisez-le pour correspondre à vos besoins.

Améliorez le SEO et l’expérience utilisateur

Le fait d’ajouter le balisage Schema.org aux sites web et applications améliore leur classement dans les résultats des moteurs de recherche et active des fonctionnalités géniales comme Google Rich Snippets et Gmail markup.

Mapper le modèle de données de votre application en structures Schema.org peut s’avérer être une tâche fastidieuse. En utilisant le générateur, votre modèle de données sera un dérivé de Schema.org.  Le fait de sérialiser vos données en JSON-LD ne requièrera pas un mapping spécifique ou une adaptation. C’est une question de minutes.

Soyez prêt pour l’avenir

Schema.org améliore l’interopérabilité de vos applications. Utilisé avec des technologies de l’hypermédia comme Hydra, il constitue un grand pas vers le web sémantique et lisible par machine. Il ouvre la voie pour permettre aux clients des API web génériques d’extraire et de traiter des données depuis n’importe quel site ou application en utilisant ces technologies.

Pour générer notre modèle de données à partir des types Schema.org, nous devons créer un fichier de configuration YAML pour PHP Schema :

# app/config/schema.yml

annotationGenerators: # Generators we want to use, keep it as is for any API Platform project
    - SchemaOrgModel\AnnotationGenerator\PhpDocAnnotationGenerator
    - SchemaOrgModel\AnnotationGenerator\DoctrineOrmAnnotationGenerator
    - SchemaOrgModel\AnnotationGenerator\ConstraintAnnotationGenerator
    - SchemaOrgModel\AnnotationGenerator\DunglasApiAnnotationGenerator
namespaces:
  entity: AppBundle\Entity # The default namespace for entities, following API Platform and Symfony best practices
types: # The list of type to generated (a PHP entity class by type will be generated)
  BlogPosting: ~ # A type to generate a PHP entity class from, including all its properties (here this type has no specific property, they are all inherited)
SocialMediaPosting:
    properties: {}
  Article: # Schema.org has an inheritance system, we will configure all types of the hierarchy
    properties: # The list of properties we want to use
      articleBody: ~
      articleSection: ~
  CreativeWork:
    properties:
      author:
        range: Person # PHP Schema handle relations. Here we force the type of the property to Person
        cardinality: (*..0) # Force the cardinality of the relation
      headline: ~
      isFamilyFriendly: ~
      datePublished: ~
  Thing:
    properties:
      name: ~
  Person: # Person is a relation of the "CreativeWork" type (property "author"), PHP Schema will generate relations for us
    properties: {} # We don't want any specific property for a person except "name" inherited from Thing

Puis exécutez le générateur :

bin/schema generate-types src/ app/config/schema.yml

Jetez un oeil au contenu du répertoire src/AppBundle/Entity. PHP Schema a généré pour nous un ensemble de bonnes vieilles entités PHP représentant notre modèle de données. Comme promis, nos entités incluent :

  • une documentation des types Schema.org convertie en PHPDoc ;
  • des annotations de mapping ORM Doctrine (y compris pour les relations) ;
  • des annotations de validation Symfony ;
  • un mapping IRI Schema.org (les annotations @Iri), nous verrons plus tard que le bundle d’API les utilise pour exposer des données sémantiques structurées ;
  • et ils suivent le style de codage PSR-2.

Le modèle de données est pleinement fonctionnel. Vous pouvez bricoler dessus (modifier les entités, les propriétés, les index, les règles de validation…) ou l’utiliser tel quel !

Demandez à Doctrine de créer la base de données du projet :

app/console doctrine:database:create

Puis générez des tables de base de données liées aux entités générées :

app/console doctrine:schema:create

PHP Schema offre de nombreuses options de configuration. Jetez un oeil à sa documentation dédiée. Gardez à l’esprit que PHP Schema est également disponible en tant qu’outil autonome (un PHAR sera prochainement disponible) et peut être utilisé pour bootstraper n’importe quel projet PHP (il fonctionne bien avec du PHP brut, API Platform et Symfony mais il a un mécanisme d’extension qui permet de l’utiliser avec d’autres technologies comme Zend Framework et Laravel).

Nous devons occasionnellement créer des modèles de données avec des types très spécifiques non disponibles dans Schema.org. Nous trouvons parfois des types Schema.org qui correspondront partiellement à ce que nous souhaitons mais qui auront besoin d’être adaptés.

N’oubliez pas que vous pouvez toujours créer votre propre modèle de données à partir de zéro. C’est parfaitement acceptable. Vous pouvez également utiliser API Platform sans PHP Schema.

PHP Schema est un outil prévu pour bootstraper le modèle de données. Vous pouvez et vous allez éditer manuellement les entités PHP générées. Quand vous commencez à éditer manuellement les fichiers générés, prenez garde à ne pas exécuter le générateur une nouvelle fois, il écraserait vos changements (ce comportement sera amélioré dans les versions futures). Lorsque vous le faites, la meilleure chose à faire est de retirer le fichier dunglas/php-schema du fichier composer.json.