link W3C close

Comment utiliser Composer avec PHP?

#1 Qu'est-ce que Composer ? open

Composer c'est un gestionnaire de dépendances. Composer va servir à télécharger et à installer des librairies php. Ces librairies sont faites de classes qui sont contenues dans des packages qui sont versionnés. Avec Composer, vous allez pouvoir demander pile-poil les versions dont vous avez besoin 😎.

Composer c'est le client d'un couple client/serveur. Le serveur par défaut, c'est le site web packagist.org (* ça peut être autre chose) et le client sous windows c'est un exécutable composer.exe (* sous Unix c'est un peu différent). Cet exécutable, vous le lancez dans une CLI (* Interface en Ligne de Commande).

Les demandes de librairies peuvent se faire en précisant une contrainte de version, par exemple ci-dessous, je demande ^6.0.0 et Composer va me donner la version la plus récente qui sera plus grande ou égale à la 6.0.0 et strictement inférieure à la 7.0.0. Par exemple, Composer va me donner précisément la 6.8.0.

Présentation de Composer

#2 Le versioning sémantique open

Le versioning sémantique ça sert à "numéroter" une version et ça sert à exprimer une contrainte de version.

Pour numéroter une version, on se sert de trois numéros :

  • Le Correctif. Il démarre à zéro et on l'incrémente à chaque fois que l'on corrige des bugs.
  • Le Mineur. Il démarre à zéro et on l'incrémente à chaque fois que l'on crée de nouvelles fonctionnalités. Quand on l'incrémente, on remet le correctif à zéro.
  • Le Majeur. Il vaut zéro quand on est en cours de développement et il démarre à 1 pour la première version beta ou stable. On l'incrémente à chaque fois que l'on fait une nouvelle version qui va entraîner une incompatibilité avec l'ancienne. Quand on l'incrémente, on remet les deux autres à zéro.

Les trois numéros sont séparés par des points. A cela, on peut rajouter un suffixe. Par exemple beta. On met un tiret entre les numéros et le suffixe.

Enfin, pour exprimer une contrainte de version, on peut aussi ajouter devant un caractère voir plusieurs.

Le versioning sémantique

#3 Démarrer un projet. Création du fichier composer.json open

Ci-dessous, je commence un petit projet qui va servir d'exemple :

  1. Pour cela, je vais me servir de Laragon. Je vais créer un nouveau projet que je vais appeler demo-composer.
  2. Ensuite, j'ouvre le terminal, je vais dans le répertoire du projet et je tape la commande composer init.
  3. Pour cet exemple, je vais répondre no à beaucoup de questions. Je ne vais définir aucune dépendance, aucune dépendance de développement, je ne vais pas demander le mapping de l'autoload.

Ci-dessous, vous pouvez voir le fichier composer.json qui a été créé.

Création d'un composer.json minimum.

Ce fichier contient un objet json. Il y a un certain nombre de propriétés : name, description ... et require. Dans un premier temps, c'est cette propriété qui va nous intéresser. Pour le moment, c'est un objet vide. Il va se remplir lorsque l'on va importer des librairies.

#4 Importation d'une librairie depuis packagist.org open

Supposons que j'ai besoin de travailler sur des URIs (* Uniform Resources Identifier). Plus précisément sur des URLs qui sont un sous-ensemble des URIs. Je veux pouvoir récupérer les infos qu'il y a dedans 😋. Le protocole, le query string, l'ancre...

Je vais sur packagist.org et je tape uri. Je trouve league/uri, je vais voir sur la page packagist de cette librairie. Puis sur la page github. Je lis le README. Il y a un exemple, ça correspond à ce que je cherche et je me dis que je vais l'importer.

Je regarde les versions disponibles. Pour la démo, je vais demander cette librairie en mettant une contrainte de version, je mets "^6.0.0". Normalement, on ne met rien et on prend la version la plus récente.

Donc, je reprends le terminal, je tape composer require league/uri "^6.0.0" (* attention, il faut mettre les doubles quote).

packagist.org me donne la version 6.8.0. Je prends VSCode et je vois que :

  1. Le fichier composer.json a été modifié.
  2. Un fichier composer.lock a été créé.
  3. Un répertoire vendor a été créé. Il contient les libraries que je viens d'importer.

Il faut remarquer qu'en fait, on a importé trois librairies dont on a les versions. On comprend bien à ce point précis la notion de gestion de dépendances. J'ai demandé une librairie, il m'en a donné trois, car la librairie que j'ai demandée dépend de deux autres. Ca bien sûr, c'est Composer qui le gère. Vous le voyez sur l'illustration ci-dessous, il y a un point d'interrogation rouge en face des traces des installations.

Importation de trois librairies.

#5 Rôles des composer.json et composer.lock open

Si j'examine le fichier composer.json, je vois que c'est la contrainte de version de ma demande qui a été notée.
Ce qu'il y a dans le composer.json
Si j'examine le fichier composer.lock, je vois que c'est la version exacte que j'ai obtenue qui a été notée.
Ce qu'il y a dans le composer.lock
Dans le composer.json, il y a ce que je demande, ce que je suis prêt à accepter en termes de version. Dans le composer.lock, il y a la version que j'obtiens précisément.
Ce qu'il y a dans le composer.json et dans le composer.lock

#6 Exploitation de la documentation de la librairie sur github open

Après exploitation du README de la doc github, je décide de garder le morceau de code ci-dessous pour tester. Je le lance dans Laragon. Et ça plante ! Ca plante parce que le code des classes que j'ai importées n'est pas inclus dans le code de l'appli.

#7 Mise en place de l'autoloader open

A ce stade, normalement, je dois ajouter dans mon index.php des instructions require pour inclure le php des classes des librairies importées. Mais Composer a mieux pour moi. Il me propose de faire un seul require d'un fichier qui s'appelle autoload.php et qui se trouve dans le répertoire vendor. Ce fichier va faire les require des classes php des librairies à ma place, et ça, c'est intéressant 😃.

#8 Coder ses propres classes et les charger avec un require en php open

Je vais créer une classe Data dans un répertoire app pour faire comme si je développais une appli complète. Je me contente dans Data de cacher une Url et je mets un getter dessus. Ca suffira pour faire un petit test.

Schéma de ma petite appli
Schéma de ma petite appli

Je mets un require pour importer ma classe. Et ça donne le code ci-dessous pour mon appli.

#9 Modifier le composer.json pour autoloader ses propres classes open

Pour cette petite appli, je pourrais en rester là, mais pour une appli plus importante, Composer propose une solution qui donne la possibilité d'autoloader les classes de l'application en plus des classes des librairies importées. Pour cela, il va falloir modifier le composer.json et ajouter la propriété ci-dessous. Dans ce petit morceau de json, je dis à Composer d'aller chercher le namespace App\ dans le répertoire app/. (* pour ceux qui seraient dubitatifs à cause du double backslash \\ au niveau du namespace. Le backslash est un caractère d'échappement pour le format json et si on veut lui enlever ce sens spécifique, il faut l'échapper lui-même, donc en mettre un devant. Du coup, ça nous en fait deux \\.)

psr-4 correspond à des recommandations qui concernent l'autoloader 😟. Ce sont des règles de nommage et d'organisation des namespaces.

Ensuite, il est nécessaire de lancer la commande composer dumpautoload pour régénérer le fichier autoload.php. Il ne reste plus qu'à faire le test avec Laragon.

#10 Composer install open

Supposons maintenant, que je mette cette application sur github. Dans le .gitignore, je vais demander à ce que le répertoire vendor, ne soit pas envoyé sur le serveur github.

Supposons maintenant, que quelqu'un fasse un git clone, pour récupérer l'appli dans un répertoire local. Il va récupérer l'appli sans le dossier vendor. Pour simuler cette situation, je supprime manuellement le dossier vendor.

A présent, j'ai besoin de restaurer vendor. Pour cela, je vais devoir faire un composer install. La commande composer install regarde s'il existe un composer.lock, si c'est le cas, elle restaure les versions exactes des librairies qui avaient été importées pour faire le projet. S'il n'y a pas de composer.lock, alors un composer install fait l'équivalent d'un composer update.

composer install
Exécution d'un composer install

#11 Composer update open

La commande composer update comme son nom l'indique, va demander une mise à jour. Pour ça, composer update travaille avec le fichier composer.json. Cette mise à jour concerne toutes les librairies que l'on a importées. Si on regarde dans vendor, on voit que chaque librairie est installée avec son fichier composer.json.

Si une mise à jour est possible et qu'une version plus récente est installée, alors ce sera noté dans le composer.lock de notre appli.

Si aucune librairie n'est installée. Un composer update va faire l'équivalent d'un composer install.

Il y a 23 options dans la doc pour cette commande composer update. Donc ici, on fait le mini.

composer update
Exécution d'un composer update

#12 Les scripts open

Dans le composer.json, vous pouvez ajouter une propriété scripts.

Il y a deux sortes de scripts :

  1. Il y a ceux qui sont déclenchés sur un événement. Par exemple l'événement post-update-cmd qui est déclenché après un composer update.
  2. Il y a ceux qui sont déclenchés de manière explicite. Par exemple en faisant une commande composer tests. Là, on déclenche le script tests.