Plongée dans l'écosystème PHP : État des lieux de la qualité du code

Share on Twitter Share on LinkedIn
You will find the 🇬🇧 english version of this article here

Un mot rapide sur l'approche

Bonjour ! Je suis Jean-François Lépine, et je m'intéresse à la qualité logicielle depuis plusieurs années. J'ai créé PhpMetrics, puis Ast-Metrics, et j'ai aidé de nombreuses entreprises à industrialiser leurs processus de développement.

Je voulais avoir une vue d'ensemble du code PHP existant, alors j'ai tout analysé. J'ai téléchargé l'intégralité de l'écosystème PHP - pas moins de 236 Go de dépôts Git contenant au total 2,3 milliards de lignes de code.

Le script d'analyse a tourné pendant trois jours complets, traitant chaque fichier. Je l'ai développé en Go pour des performances optimales et un contrôle précis du CPU - l'analyse PHP à cette échelle nécessite une optimisation sérieuse.

TL;DR - Trop long ? Pas lu ? Voici la version courte !

Le PHP open-source est moderne, modulaire et maintenable. Mais attention à la dépendance excessive à quelques packages centraux et aux projets sous-maintenus.

Le PHP moderne est modulaire et concis
  • 36% des fichiers ont moins de 100 lignes de code
  • L'utilisation intensive des interfaces rend l'écosystème hautement modulaire.
La complexité est globalement maîtrisée, mais...
  • 76,5% des fichiers ont une faible complexité cyclomatique (0-10).
  • Cependant, 23,5% du code est complexe, posant un défi de maintenabilité
Dépendance extrême à un petit ensemble de packages
  • Seulement 136 packages (0,05%) représentent 50% de tous les téléchargements.
  • Ces bibliothèques centrales sont bien maintenues, mais créent des risques de dépendance importants.
Le problème de "l'infrastructure fantôme"
  • Certains packages très utilisés reçoivent très peu de reconnaissance (peu d'étoiles GitHub).
  • Des dépendances critiques peuvent être maintenues par de très petites équipes.
L'écosystème PHP est sain mais vieillissant
  • 70% des packages montrent une activité minimale.
  • 23% semblent abandonnés, rendant l'audit des dépendances essentiel.

Radiographie de l'écosystème Open Source PHP

Open Source vs Contexte Entreprise :

Il est important de noter que ces métriques proviennent de projets open-source, qui diffèrent significativement des bases de code typiques d'entreprise. Les bibliothèques open-source privilégient souvent l'extensibilité et l'abstraction (ce qui explique le ratio élevé interfaces/classes), tandis que les projets d'entreprise se concentrent davantage sur l'implémentation de la logique métier et des cas d'utilisation spécifiques. Lors de l'évaluation de votre propre base de code, considérez si votre contexte s'aligne davantage avec les modèles de conception de bibliothèques ou les implémentations spécifiques aux applications.

J'ai analysé 11,1 millions de fichiers PHP, totalisant plus de 707,6 millions de lignes de code PHP — faisant partie d'un impressionnant total de 2,3 milliards de lignes de code toutes langues confondues dans l'écosystème Packagist. Ces métriques offrent un aperçu réel de la structure du PHP dans la nature, au-delà des bonnes pratiques théoriques.

Distribution de la taille des fichiers

Une écrasante majorité de 36% des fichiers contiennent moins de 100 lignes de code logique, avec une médiane de seulement 4,0 lignes.

Cela révèle une forte préférence à l'échelle de l'écosystème pour des implémentations petites et ciblées - bien plus petites que ce que la plupart des guides de style suggèrent comme maximum. Cela reflète également l'utilisation massive des interfaces dans l'écosystème, avec 3,7M d'interfaces comparé à 7,4M de classes - beaucoup de ces interfaces ne contenant aucun code logique, uniquement des signatures de méthodes.

Complexité Cyclomatique

76,5% des fichiers maintiennent une faible complexité (0-10), tandis que 23,5% s'aventurent dans un territoire de plus haute complexité.

Même avec un accent mis sur les petits fichiers, près d'un quart de la base de code montre encore une complexité significative – mettant en évidence des zones où la maintenabilité pourrait être problématique.

Packages Analysés

411,6K

Packages PHP de l'écosystème PHP

Fichiers

11,1M

Fichiers PHP détectés

Méthodes

53,4M

Méthodes PHP analysées

Lignes de Code

707,6M

Total des lignes de code
Dont 362,9M lignes de code logique

Distribution des lignes de code logique

Distribution de la complexité cyclomatique

Concentration des téléchargements : Le fondement de PHP

L'un des aspects les plus révélateurs de l'écosystème PHP est l'extrême concentration des téléchargements.

Les données montrent que seulement 136 packages (0,05 % de tous les packages) représentent plus de la moitié de tous les téléchargements mensuels dans l'ensemble de l'écosystème.

Cette concentration reflète plusieurs dynamiques importantes dans le monde PHP :

Une base consolidée

L'écosystème PHP a mûri pour s'appuyer sur un ensemble relativement restreint de bibliothèques centrales qui fournissent des fonctionnalités essentielles. Cette base stable signifie que les développeurs n'ont pas besoin d'évaluer constamment des implémentations concurrentes pour les besoins fondamentaux.

Effets de chaîne des dépendances

De nombreux packages populaires sont des éléments fondamentaux qui sont inclus comme dépendances transitives dans des milliers de projets. Cet effet en cascade amplifie le nombre de téléchargements pour ces packages fondamentaux.

🎉 Les bonnes nouvelles

La découverte encourageante est que ces packages à fort impact sont très majoritairement bien maintenus et sains :

  • Presque tous les packages populaires ont des communautés de contributeurs actives
  • La plupart disposent de suites de tests robustes et de pipelines CI/CD
  • Beaucoup sont soutenus par des entreprises ou des fondations assurant leur stabilité à long terme

Dominance des téléchargements

Packages qui représentent collectivement 50% ou plus des téléchargements mensuels

Nombre de packages dominants

136

% du total des téléchargements

0,05

Total des téléchargements mensuels

2808,6M

2808.6M

Package Monthly downloads % Stars
symfony/deprecation-contracts 15.7M 0.55 2053.0
symfony/polyfill-mbstring 15.5M 0.55 7847.0
psr/log 15.2M 0.55 10421.0
psr/container 15.0M 0.55 9981.0
symfony/console 14.9M 0.55 9785.0
symfony/service-contracts 14.7M 0.5 2595.0
symfony/polyfill-intl-normalizer 14.6M 0.5 2026.0
psr/http-message 14.5M 0.5 6998.0
guzzlehttp/psr7 14.2M 0.5 7905.0
guzzlehttp/promises 14.1M 0.5 7645.0
symfony/process 14.1M 0.5 7453.0
symfony/polyfill-ctype 14.1M 0.5 4056.0
symfony/finder 14.0M 0.5 8436.0
guzzlehttp/guzzle 14.0M 0.5 23313.0
symfony/string 13.9M 0.5 1741.0
ralouphie/getallheaders 13.9M 0.5 3778.0
psr/http-factory 13.6M 0.5 1827.0
nikic/php-parser 13.6M 0.5 17179.0
symfony/polyfill-php80 13.6M 0.5 1731.0
symfony/polyfill-intl-grapheme 13.6M 0.5 1689.0
psr/http-client 13.3M 0.45 1685.0
symfony/event-dispatcher 13.3M 0.45 8534.0
monolog/monolog 13.1M 0.45 21132.0
symfony/event-dispatcher-contracts 13.1M 0.45 3394.0
symfony/var-dumper 13.0M 0.45 7426.0
myclabs/deep-copy 12.8M 0.45 8807.0
phpunit/phpunit 12.7M 0.45 19791.0
symfony/http-foundation 12.7M 0.45 8652.0
sebastian/diff 12.6M 0.45 7600.0
doctrine/lexer 12.6M 0.45 11102.0
symfony/translation-contracts 12.4M 0.45 2576.0
phpunit/php-code-coverage 12.3M 0.45 8863.0
symfony/polyfill-intl-idn 12.3M 0.45 3339.0
sebastian/comparator 12.3M 0.45 7024.0
sebastian/exporter 12.3M 0.45 6801.0
psr/event-dispatcher 12.2M 0.45 2209.0
phpunit/php-file-iterator 12.2M 0.45 7444.0
sebastian/recursion-context 12.2M 0.45 6556.0
sebastian/global-state 12.1M 0.45 6584.0
sebastian/version 12.1M 0.45 6557.0
phpunit/php-timer 12.1M 0.45 7684.0
sebastian/environment 12.1M 0.45 6752.0
webmozart/assert 12.1M 0.45 7588.0
phpunit/php-text-template 12.1M 0.45 7389.0
symfony/http-kernel 12.0M 0.45 8126.0
sebastian/object-enumerator 12.0M 0.45 6507.0
sebastian/code-unit-reverse-lookup 11.9M 0.4 6690.0
symfony/yaml 11.9M 0.4 3826.0
symfony/error-handler 11.9M 0.4 2623.0
theseer/tokenizer 11.9M 0.4 5177.0
phar-io/manifest 11.9M 0.4 7431.0
symfony/translation 11.9M 0.4 6620.0
sebastian/object-reflector 11.8M 0.4 6257.0
symfony/mime 11.8M 0.4 2794.0
phar-io/version 11.8M 0.4 7429.0
symfony/routing 11.8M 0.4 7623.0
psr/simple-cache 11.5M 0.4 8104.0
sebastian/type 11.5M 0.4 1434.0
doctrine/inflector 11.5M 0.4 11290.0
psr/cache 11.2M 0.4 5138.0
egulias/email-validator 11.2M 0.4 11517.0
sebastian/cli-parser 11.1M 0.4 1132.0
symfony/css-selector 11.1M 0.4 7440.0
sebastian/complexity 11.1M 0.4 1183.0
sebastian/lines-of-code 11.0M 0.4 1101.0
phpunit/php-invoker 11.0M 0.4 1256.0
ramsey/uuid 11.0M 0.4 12515.0
sebastian/code-unit 11.0M 0.4 1131.0
psr/clock 10.9M 0.4 526.0
doctrine/deprecations 10.7M 0.4 1707.0
brick/math 10.6M 0.4 1907.0
ramsey/collection 10.4M 0.35 1153.0
nesbot/carbon 10.1M 0.35 48.0
symfony/polyfill-php83 9.8M 0.35 357.0
league/flysystem 9.7M 0.35 13410.0
league/mime-type-detection 9.6M 0.35 1300.0
symfony/mailer 9.6M 0.35 1527.0
doctrine/instantiator 9.4M 0.35 10975.0
symfony/filesystem 9.2M 0.35 4621.0
vlucas/phpdotenv 9.0M 0.3 13265.0
phpoption/phpoption 8.9M 0.3 2644.0
psy/psysh 8.7M 0.3 9767.0
dragonmantank/cron-expression 8.6M 0.3 4594.0
nette/utils 8.5M 0.3 2034.0
carbonphp/carbon-doctrine-types 8.4M 0.3 156.0
tijsverkoyen/css-to-inline-styles 8.4M 0.3 5826.0
voku/portable-ascii 8.4M 0.3 555.0
composer/semver 8.4M 0.3 3195.0
fakerphp/faker 8.3M 0.3 3696.0
graham-campbell/result-type 8.3M 0.3 504.0
paragonie/random_compat 8.2M 0.3 8178.0
laravel/serializable-closure 8.2M 0.3 550.0
dflydev/dot-access-data 8.2M 0.3 666.0
symfony/options-resolver 8.1M 0.3 3222.0
phpdocumentor/type-resolver 8.1M 0.3 9161.0
phpstan/phpdoc-parser 8.0M 0.3 1398.0
symfony/polyfill-php81 8.0M 0.3 877.0
symfony/polyfill-uuid 8.0M 0.3 657.0
doctrine/dbal 8.0M 0.3 9554.0
phpdocumentor/reflection-common 7.9M 0.3 9045.0
league/commonmark 7.9M 0.3 2807.0
symfony/uid 7.9M 0.3 568.0
laravel/framework 7.9M 0.3 33237.0
nette/schema 7.8M 0.3 939.0
composer/pcre 7.8M 0.3 597.0
mockery/mockery 7.8M 0.3 10661.0
doctrine/event-manager 7.8M 0.3 5964.0
firebase/php-jwt 7.7M 0.3 9526.0
hamcrest/hamcrest-php 7.7M 0.3 6970.0
aws/aws-sdk-php 7.7M 0.3 6082.0
symfony/var-exporter 7.7M 0.25 2065.0
mtdowling/jmespath.php 7.7M 0.25 1954.0
sebastian/resource-operations 7.5M 0.25 6281.0
league/flysystem-local 7.5M 0.25 180.0
laravel/tinker 7.4M 0.25 7363.0
phpdocumentor/reflection-docblock 7.4M 0.25 9360.0
league/config 7.4M 0.25 519.0
doctrine/cache 7.4M 0.25 7868.0
paragonie/constant_time_encoding 7.1M 0.25 836.0
phpseclib/phpseclib 7.1M 0.25 5434.0
aws/aws-crt-php 7.1M 0.25 367.0
filp/whoops 7.0M 0.25 13218.0
phpstan/phpstan 7.0M 0.25 13240.0
guzzlehttp/uri-template 6.9M 0.25 154.0
nunomaduro/termwind 6.9M 0.25 2377.0
symfony/config 6.7M 0.25 4248.0
laravel/prompts 6.7M 0.25 562.0
fruitcake/php-cors 6.7M 0.25 261.0
symfony/dependency-injection 6.7M 0.25 4130.0
symfony/http-client-contracts 6.6M 0.25 1952.0
symfony/polyfill-php73 6.6M 0.25 2399.0
symfony/clock 6.5M 0.25 353.0
league/uri-interfaces 6.5M 0.25 482.0
symfony/cache 6.5M 0.25 4125.0
league/uri 6.5M 0.25 1060.0
doctrine/annotations 6.4M 0.25 6742.0

L'Infrastructure Invisible : Les Packages à Fort Impact mais Peu Reconnus

En analysant la relation entre les étoiles GitHub et le nombre de téléchargements, j'ai découvert un sous-ensemble fascinant de packages PHP : ceux qui ont des nombres de téléchargements massifs mais étonnamment peu d'étoiles. Ces packages forment ce qu'on pourrait appeler "l'infrastructure invisible" de PHP — des composants d'une importance cruciale qui opèrent silencieusement sous la surface d'innombrables applications.

Ce "déficit de reconnaissance" a plusieurs implications importantes :

  • Les packages à fort impact mais à faible visibilité peuvent avoir du mal à attirer des contributeurs
  • Des dépendances critiques peuvent être maintenues par de petites équipes malgré leur importance démesurée dans l'écosystème
  • Cependant, beaucoup représentent des opportunités pour les développeurs cherchant à apporter des contributions significatives à l'écosystème PHP

Packages populaires

En contraste, ces packages sont à la fois très populaires et largement utilisés. Ils constituent la pierre angulaire de PHP.

taille des bulles proportionnelle aux forks GitHub

État de santé de l'écosystème Packagist

L'analyse des packages PHP révèle des préoccupations importantes concernant la santé de l'écosystème Packagist : 70% montrent une activité minimale avec peu de téléchargements et d'interactions GitHub, tandis que 23% semblent abandonnés sans mises à jour récentes. Avec une moyenne de seulement 60 étoiles par package (fortement influencée par les cas exceptionnels populaires), ces métriques mettent en évidence la distribution typique en "longue traîne" des écosystèmes open source. Ces données soulignent l'importance d'évaluer soigneusement la santé des dépendances à travers des métriques comme le facteur bus, la fréquence des mises à jour et l'engagement de la communauté lors de l'intégration de packages dans des projets de production.

Packages vides

94,9K

Packages abandonnés

Packages fantômes

288,5K

Packages avec peu de téléchargements, peu d'étoiles ou de forks GitHub

Popularité moyenne

60

Moyenne d'étoiles par package
Excluant les packages sans étoiles

Et qu'en est-il de la qualité ?

Malgré la réputation parfois critiquée de PHP, les données racontent une histoire différente. Les packages PHP montrent un code étonnamment propre, facile à maintenir et à comprendre. Les fonctions sont remarquablement courtes, les différentes parties du code s'harmonisent bien et les packages gardent une taille raisonnable. Il s'avère que les développeurs PHP n'écrivent pas du code spaghetti après tout - ils élaborent des plats bien structurés qui feraient hocher la tête d'approbation même aux chefs de code les plus exigeants.

Distribution de la complexité

Complexité cyclomatique moyenne

8,8

Complexité cyclomatique médiane

4,0

Qualité du code

Indice de maintenabilité

108

Lignes par méthode

3,0

Packages avec le plus de lignes de code

Si vous êtes curieux des packages ayant le plus de lignes de code, vous trouverez les 100 premiers packages ci-dessous. Notez que les plus gros packages concernent les données géographiques et intègrent beaucoup de données dans leur code.

Que cache-t-on d'autre dans les dépôts PHP ?

Analyser PHP sur Packagist est une chose, mais qu'en est-il de tout ce qui entoure PHP ? En réalité, les projets PHP modernes s'appuient sur une pile technologique diverse.
🔍 Voici ce que j'ai trouvé dans les dépôts :
  • PHP domine (plus de 707M lignes de code), mais il est loin d'être seul.
  • JavaScript est le compagnon le plus courant (plus de 216M lignes), prouvant que l'intégration front-end et back-end est essentielle.
  • JSON & YAML sont omniprésents (plus de 200M lignes combinées), soulignant l'essor des architectures pilotées par la configuration.
  • CSS & HTML (plus de 167M lignes au total) démontrent la nature full-stack de nombreuses applications PHP.
  • SQL, XML et Markdown reflètent l'importance des données structurées et de la documentation dans les projets PHP modernes.
💡 Découvertes surprenantes :
  • TypeScript est en croissance (2,7M lignes) – les projets PHP deviennent-ils plus structurés côté front-end ?
  • C, Go et Rust apparaissent en petites quantités – un signe d'extensions critiques en performance ?
  • Même Lua, Perl et Scheme font leur apparition – des intégrations héritées ou des outils de script au sein des projets PHP ?

👉 Le PHP moderne est plus que du PHP. C'est un écosystème qui se mélange avec diverses technologies, rendant les compétences multi-langages de plus en plus précieuses pour les développeurs PHP.

Répartition des lignes de code par langage (top 10)

Et après ?

Maintenant que la majorité du processus est automatisée, il me reste encore quelques nettoyages de code à effectuer, mais je pense qu'il serait utile de réaliser cette analyse au moins deux fois par an pour maintenir une vue actualisée de l'écosystème PHP. Jusqu'à présent, je me suis concentré exclusivement sur Packagist, mais ce n'est pas le seul gestionnaire de packages - l'ajout de nouvelles sources de code fournirait une image plus complète.

J'envisage également d'implémenter des métriques de code plus avancées pour approfondir l'analyse. Les métriques actuelles nous donnent une bonne base, mais il y a toujours plus à apprendre sur la qualité du code et la santé de l'écosystème.

Si vous avez des idées de métriques ou de fonctionnalités supplémentaires qui pourraient améliorer ce tableau de bord, n'hésitez pas à me contacter - vos suggestions pourraient aider à façonner l'orientation future de ce projet !

blog comments powered by Disqus

© Jean-François Lépine, 2013 - 2025