Accueil > Ailleurs > Ça parle de PHP en général > Composer

Composer

vendredi 30 mars 2018, par James

Après avoir évoqué les effets positifs qu’il avait apporté à la communauté PHP depuis plus de 6 ans dans l’article sur les Statistiques Mars 2018, je propose, à ceux qui ne le connaîtrait pas encore, de découvrir composer dans les grandes lignes, et d’imaginer comment il pourrait être utile à SPIP.

L’idée de ce billet n’est pas de détailler absolument toutes les options de l’outil, ni de traduire intégralement sa documentation en français. Juste de présenter ses mécanismes les plus importants, d’introduire les concepts sur lesquels il s’appuie.

TL ;DR

Pour celles et ceux qui n’auront pas le courage de lire jusqu’au bout et de cliquer pour aller lire quelques pages en anglais, sachez ceci :

Composer intervient essentiellement pendant la phase de développement. Mais il peut aussi avoir son utilité pendant la phase de packaging voire pour une partie du déploiement d’une application web.

James, 30 mars 2018, minuit 8.

Des liens pour commencer

Quelques définitions

J’emploie un vocabulaire particulier. Je vous propose quelques définitions, appliquées à l’écosystème de SPIP ici :

  • Application web : Tout le code d’un SPIP Classique et son organisation. Le cœur de SPIP et ses plugins, d’autres plugins, le squelette par défaut ainsi que toutes les personnalisations du site, tous langages confondus. SPIP n’est donc pas à considérer comme une application web mais comme un (très gros) composant, ou un assemblage de composants permettant de réaliser une application.
  • Composant : SPIP, un plugin SPIP [1], une librairie qui vient d’ailleurs, un squelette, voire un thème graphique.
  • Packaging : Fabriquer le paquet d’un composant (du plus petit plugin au cœur de SPIP) ou d’une application web et le mettre à disposition du public.
  • Déploiement : pousser une application web sur un ou plusieurs serveurs ou récupérer depuis ce ou ces serveurs le paquet de l’application web. Puis faire toutes les opérations particulières liées à l’installation, la mise à jour du code, la création ou la mise à jour des tables de la base de données, et bien d’autres choses. Tout cela sans préjuger de la manière de faire (à la main, automatiquement, via une page web de configuration, en ligne de commande...).

À quoi sert cet outil ?

En gros, il s’agit d’un outil de gestion de dépendances, écrit en PHP. C’est-à-dire que son rôle, pendant la phase de développement d’un projet [2], sera d’installer et de mettre à jour les composants nécessaires à son fonctionnement de base ou de l’enrichir de fonctionnalités distribuées sous forme de bibliothèque (library, en anglais).

Bref, son boulot, c’est d’assembler des composants en tout genre, mais surtout en PHP, en s’assurant qu’il sont compatibles entre eux. Il s’appuie pour cela sur la présence d’un fichier composer.json dans chaque « branche » ou chaque « tag » de la gestion de sources (svn ou git) du composant. Ce fichier détermine les dépendances, i.e. d’autres composants, leur version souhaitée, ainsi que quelques contraintes plus générales éventuellement.

Arrivé là, je devrais expliquer comment fonctionne la résolution des dépendances. La page dédiée est très riche.

Disons pour le moment qu’un composant, quel qu’il soit, va être mis à disposition dans plusieurs versions, éventuellement à plusieurs niveaux de stabilité, et qu’en fonction de cette combinaison, la personne qui souhaite l’intégrer à son projet récupèrera la version qui convient le mieux aux contraintes qu’elle s’est fixée pour utiliser ce composant.

Pour cela, composer s’appuie sur la spécification Gestion sémantique de version et donc, pour lui, la version est à la fois ce qu’on appelle dans SPIP, la version et l’état. En gros, au lieu d’avoir 2 attributs qui définissent sa version et son état, un composant est versionné avec un seul terme qui combine les deux attributs. Composer ira chercher la combinaison qui sied le mieux, en se basant sur les contraintes définies dans le projet.

J’ajouterai que le terme qui définit la version du composant, c’est le nom de la branche (de maintenance ou de développement) ou le libellé du tag (la release, ou la publication, si vous préférez), que cela donne un sens particulier aux répertoires trunk, branches et tags d’un dépôt svn. Composer déduit du libellé des tags la version et le niveau de stabilité du composant, ces valeurs ne sont pas gérées dans le fichier composer.json. Et je m’arrête là, pour l’instant, sur l’aspect résolution de dépendances...

Contrairement aux gestionnaires de paquets de Debian ou Fedora, mais aussi à PEAR, l’ancien gestionnaire de dépendances de PHP qu’il remplace petit à petit, composer s’occupe des dépendances au niveau du projet principalement et pas globalement pour le système sur lequel il est installé. C’est donc au cas par cas qu’il va résoudre les contraintes de dépendances. On pourra donc trouver sur un même serveur, des applications utilisant le même composant, mais dans des versions différentes. Un avantage induit, c’est qu’il n’est pas nécessaire d’être « root » sur le serveur pour installer des paquets [3].

Pour les pratiquantes PHP, il offre un moyen simple de charger le fichier PHP nécessaire à l’exécution d’une fonction [4] : l’autoloading. Il peut s’appuyer pour cela sur 4 méthodes :

  • psr0 dépréciée mais encore supportée,
  • psr4,
  • classmap et
  • files.

Les deux premières méthodes sont basées sur des recommandations mises au point par des représentants de différents CMS, Frameworks ou d’outil de développements PHP bien connus, rassemblés sous le nom de FIG [5]. Plutôt destinées aux composants écrit en mode objet, il y aura un long travail à produire avant qu’elles ne soient appliquées dans le cœur de SPIP lui-même.

Mais il pourrait d’ores et déjà s’appuyer sur la multitude des composants qui appliquent les recommandations du FIG et que la communauté PHP met à disposition librement, car composer produit un « autoloader » permettant de faire cohabiter des composants basés sur toutes ces méthodes. En effet, pour un projet donné, composer produira un seul autoloader qui agrègera l’autoloading de tous les composants requis.

La méthode classmap permet d’intégrer à l’autoloader des classes d’objets qui ne sont pas organisées comme psr0 et psr4 l’imposent. Tout se fait plus ou moins à la main, mais ça marche... Et c’est un excellent moyen pour reprendre un code, objet certes, mais pas « psr4 », de mettre en place composer, et de migrer tranquillement vers une méthode d’autoloading plus performante.

La méthode files permet d’intégrer à l’autoloader des fichiers qui seront chargés à chaque appel (un bon gros require_once en somme). C’est un moyen utile pour définir des constantes ou des fonctions PHP de base. Dans le cas de SPIP, on pourrait imaginer que son autoloader intègrerait les fichiers ecrire/inc/utils.php, config/mes_options.php, config/ecran_securite.php, voire ecrire/inc_version.php sous réserve de quelques modifications. Mais il y a d’autres cas d’utilisation possibles. On reste dans les grandes lignes ;-)

Il permet aussi de séparer les composants nécessaires à l’application de ceux requis pour le développement de cette application, comme, et ce n’est qu’un exemple, des tests unitaires isolés. De sorte qu’on peut limiter l’autoloader au strict nécessaire sur un environnement de production si on le souhaite.

Ce qui devient intéressant, c’est que ce système permet d’avoir le choix de la gestion de version et de la plate-forme de développement, car composer sait :

  • récupérer du code source sur un dépôt svn ou git [6],
  • sur à peu près toutes les plates-formes de partage de code : github, bitbucket, gitlab ou n’importe quelle plate-forme indépendante, comme SPIP-zone, pour peu qu’elle héberge des composants identifiables [7],
  • ou bien télécharger des ZIPs
  • et ceci à travers un mécanisme formalisé qu’on appelle un dépôt composer.

Un dépôt composer consiste en un fichier au format JSON accessible sur le web. Le plus connu et le plus utilisé est celui fourni par https://packagist.org.

Il est malgré tout possible d’avoir son propre dépôt composer, public ou privé, et il existe de nombreuses solutions, certaines payantes, d’autres libres, certaines sont un peu plus basiques, d’autres sont de véritables usines à gaz... Il y en a pour tous les goûts ! Il serait même possible d’inventer la sienne si on veut vu que les spécifications sont ouvertes.

Bref, ce fichier JSON décrit les composants qu’il est capable de distribuer, en fournissant l’URL d’un zip à télécharger ou de l’adresse de la gestion de source, ou les deux, et ceci pour chaque version connue. Ainsi, composer, toujours en s’appuyant sur les contraintes du projet, ira chercher un zip à télécharger pour l’installer, ou remplacer le code lors d’une mise à jour avec un autre zip plus à jour du même composant. Ou bien récupérer le code via SVN ou GIT... Pour un dépôt composer, un paquet, ce n’est pas seulement le zip du code, mais un ensemble de références de téléchargement.

Si un jour, un composant existe sous une nouvelle version, ou mieux, s’il passe d’un développement sur SVN à un développement sur GIT, une fois le dépôt composer informé de ce changement, le projet pourra être mis à jour avec une simple commande composer ... je dis ça, je dis rien :-)

Coté packaging, les archives de chaque version peuvent être générés par un dépôt composer ou récupérés dans la gestion de version (pas dans SVN, mais les plates-formes de type github/gitlab/etc. génèrent des zips compatibles). Si on est motivé, on peut continuer à produire les zips avec un système tiers et les référencer dans le dépôt. Encore une fois, le choix est vaste. Et les personnes qui produisent les paquets Debian de SPIP pourraient sans doute apprécier de pouvoir utiliser un outil assez commun aujourd’hui pour leur assemblage.

J’ai évoqué le sujet dans mon billet précédent, pour partie de la phase d’installation/mise à jour, le déploiement de SPIP repose sur plusieurs techniques actuellement. Il y aurait fort à gagner à centraliser ces méthodes autour de ce que propose composer.

Je crois qu’on a fait le tour. J’aurais pu aussi détailler à quoi composer ne doit pas servir, mais ce sera tout pour l’instant. :-)


[1core ou pas core, n’importe quel plugin.

[2pour faire simple, on dira « une application web écrite en PHP », mais cela pourrait être un simple composant générique, un plugin pour cette application, un outil en ligne de commande, un web service, ou un service tout court qui tourne sur une machine Linux...

[3Si on utilise composer pour faire ses installations et ses mises à jour sur un serveur, cela va sans dire !

[4fonction au sens large, bien que particulièrement efficace quand on programme en mode objet

[5le Framework Interop Group met à disposition ses recommandations sur le site https://www.php-fig.org/

[6et même mercurial ou fossil

[7ça pourrait faire l’objet d’un article entier, mais pour SPIP-Zone, ce serait possible, framagit aussi

Messages

Un message, un commentaire ?

Qui êtes-vous ?
Se connecter
Votre message

Ce formulaire accepte les raccourcis SPIP [->url] {{gras}} {italique} <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.