Gérer ses dépendances PHP avec Composer

Installer, utiliser et comprendre Composer
31/07/2015

Gérer ses dépendances PHP avec Composer

Que ce soit pour publier votre librairie PHP ou pour en utiliser une, le plus simple, c'est d'utiliser Composer qui permet à partir d'un simple fichier json, de donner un maximum d'informations sur votre projet et sur ceux dont il dépend.

Installation

Avant de pouvoir utiliser composer, il va falloir l'installer. Ce gestionnaire de dépendance pour PHP a été lui-même écrit en PHP et est donc disponible sous forme de PHAR (PHP Archive) qu'il suffit de télécharger et d'exécuter (sous réserve d'avoir PHP installé).

Pour l'installer, suivez les instructions présentes sur le site :

Vous avez installé composer ? Commençons à gérer nos dépendances !

Initialisation du projet

Pour initialiser votre projet avec composer, le plus simple, c'est dans le dossier de votre projet, à la racine (ce n'est pas obligatoire, mais très fortement conseillé), vous pouvez exécuter la commande suivante dans votre console (en supposant que la commande "composer" exécute votre composer.phar comme indiqué dans les liens d'installation ci-dessus)

composer init

Une fois cette commande effectuée, plusieurs éléments vont vous être demandés :

  1. Package name (<vendor>/<name>) : Entrez ici le nom de votre package. Ce nom est extrêmement important si vous désirez publier votre librairie, puisque c'est grâce à lui que votre projet sera identifié. <vendor> correspond à votre organisation, et <name> au nom de votre librairie. Par exemple, si nous proposions une librairie permettant de faire du café, nous pourrions l'appeler umanit/coffee ;
  2. Description : Description de votre package. Utilisé par les interfaces permettant de recenser les librairies (comme packagist, le plus célèbre) ;
  3. Author : Le ou les auteurs du projet ;
  4. Minimum stabilité : Stabilité minimum des librairies dont le projet dépend (en savoir plus). Il est fortement recommandé de mettre le niveau le plus haut, à savoir stable ;
  5. Package Type : Les 2 valeurs à retenir pour ce paramètre sont library (par défaut) si notre projet n'est qu'une librairie visant à être utilisée par de plus gros projets, et project lorsque c'est un projet complet (du genre un site web, un framework, etc..). D'autres valeurs existent, mais sont rarement utilisées ;
  6. Enfin, composer va vous demander si vous souhaitez ou non définir vos dépendances (require et required-dev), nous y reviendrons dans la prochaine section ;

Vous voilà avec un fichier composer.json tout neuf, à la racine de votre projet ! C'est ce fichier qu'il faudra éditer (via votre éditeur préféré ou via la commande composer) pour ajouter des informations sur votre projet.

Les dépendances

Il existe 5 attributs permettant de donner un maximum d'informations sur vos dépendances : require, required-dev, replace, suggest, conflict. Les deux premiers vont être détaillés ci-après car ce sont les plus importants, mais vous pouvez en apprendre plus avec leur documentation.

Considérons, une partie d'un composer.json comme ci-dessous

"require": {
    "silex/silex": "1.2",
    "monolog/monolog": "~1.12"
},
"require-dev": {
    "phpunit/phpunit": "4.5.0"
}

Deux sections require et require-dev font leur apparition, la syntaxe est la même, mais le résultat ne l'est pas.

Le "require"

Le require fait référence aux librairies à utiliser dans n'importe quel environnement. Elles sont indispensables à votre application.
C'est un objet JSON contenant en clé le nom de la librairie (valeur du "package name" vu auparavant), et la version à utiliser. Il existe de très nombreuses manières de définir la version des librairies à utiliser, à vous de choisir la bonne, mais quoi qu'il en soit, il faut que celle-ci soit cohérente avec votre "minimum-stability" défini dans votre composer.json. (Ne mettez pas de librairies à "dev" si vous ne voulez que des "stable", ça ne fonctionnera pas)

Pour ajouter une ligne dans vos "require", vous pouvez le faire manuellement, mais il existe une commande qui ajoutera la ligne et téléchargera la lib automatiquement :

composer require {lib} {version}

Le "require-dev"

Le require-dev fonctionne de la même manière que require, sauf que toutes les librairies se trouvant sous cette section, ne seront pas installées en mode "--no-dev". C'est par exemple ici que vous mettrez vos librairies de test unitaire, fonctionnel ou toute autre librairie ne servant qu'à votre développement.

L'autoloading

Maintenant que l'on a défini nos dépendances, nous allons pouvoir nous intéresser à la configuration de notre projet.

En PHP objet, l'autoloading des classes est souvent un problème. Composer vous permet de ne pas avoir à vous en préoccuper. Prenons l'exemple suivant issu d'un composer.json :

"autoload": {
     "psr-4": {
         "": "src",
        "Umanit\\":"dep/"
     }
}

Sous le paramètre autoload du composer se trouve un objet décrivant quel type d'autoloading utiliser, et pour chacun de ces types, le namespace de base avec le dossier cible.

Pour le type d'autoloading, deux possibilités, psr-0 ou psr-4. Quelle différence pour composer ? en PSR-4 vous n'avez pas besoin de regénérer votre autoload quand vous ajoutez une classe. Suivez-donc la norme psr-4 plutôt que psr-0 ;)

Pour ce qui est de la liste des namespaces, c'est relativement simple :

  1. En clé, vous mettez la base de vos namespaces ;
  2. En valeur, le dossier dans lequel se trouvent ces classes ;

Exemples avec la configuration ci-dessus :

  1. Pour une classe se trouvant dans src/Umanit/Test/MyClass.php, composer s'attend à ce que le namespace soit Umanit\Test
  2. Pour une classe se trouvant dans dep/Under/Test/MyClass.php, composer s'attend à ce que le namespace soit Umanit\Under\Test

Note : Une section autoload-dev fonctionnant comme autoload existe pour spécifier les classes à ne charger qu'en environnement de dev.

Installation des librairies

Une fois votre configuration prête dans votre composer.json, il ne vous reste plus qu'une commande à effectuer

composer install

Cette commande téléchargera les librairies (dans le dossier vendor/ par défaut) dans les versions que vous avez spécifiées dans votre composer.json et créera par la même occasion, un fichier composer.lock qui contiendra la version exacte de chaque librairie que vous avez installé. Ainsi, lors d'un prochain composer install, peu importe la version que vous aurez mise dans votre composer.json, seul le composer.lock sera lu. Il est donc indispensable de versionner dans votre CVS favori ce fameux fichier, afin d'être certain que tous les membres de l'équipe, mais également votre production, aient exactement les mêmes versions de lib que vous.

Pour ne pas installer les librairies qui sont sous require-dev, vous devez spécifier l'option --no-dev (à utiliser notamment sur votre environnement de production)

composer install --no-dev

Il arrive toutefois de vouloir mettre à jour une librairie. Pour cela, après avoir modifié la version dans votre composer.json, vous devez exécuter la commande suivante :

composer update {lib}

Vous pouvez omettre le paramètre {lib} et ainsi mettre à jour toutes vos librairies d'un coup, mais c'est très fortement déconseillé, d'autant plus si vous n'avez pas bien fixé toutes les versions dans votre composer.json.

Installation depuis un dépôt privé

Par défaut, composer va chercher ses librairies sur Packagist, une bibliothèque de tout un tas de librairies PHP. Mais on a parfois besoin de récupérer une librairie venant d'ailleurs, d'un fork ou d'un CVS privé. Pour cela, plusieurs possibilités existent :

  1. Créer un dépôt pour composer privé avec Satis
  2. Définir où chercher une librairie grâce à la section repositories ;

Par exemple, si vous devez chercher une librairie sur un de vos dépôts git :

"repositories" : [
    { 
        "type" : "git",
        "url" : "https://github.com/xxxxx/xxxx.git"
    }
]

Il faut bien sûr que l'URL soit accessible depuis les machines procédant à un composer install.

Pour en apprendre davantage sur la configuration des repositories, veuillez consulter la documentation.

Utilisation

Maintenant que vous avez tout installé, vous devriez trouver dans votre dossier vendor un fichier autoload.php. Il ne vous reste plus qu'à l'inclure dans l'index de votre projet (ou ailleurs si tout votre projet ne nécessite pas cet autoloader)

require_once __DIR__.'/vendor/autoload.php'

Et voilà, votre projet est prêt à fonctionner avec l'ensemble des librairies dont vous rêviez !

Pour conclure, en bref

Composer est un excellent outil pour bien gérer l'architecture de son application. Il existe des dizaines d'options de configuration qui mériteraient d'être détaillées, comme les scripts permettant d'exécuter du code ou des commandes avant ou après certains événements (composer install, update, archive, status).