Blog / Article #160
Refactoring PHP legacy avec des LLM : la galère transformée en partie de plaisir (ou presque)

star

04 Novembre 2026
Une main stylisée interagit avec une interface en ligne de commande futuriste, entourée de fragments de code PHP et de flux de données abstraits en bleu et violet, illustrant un agent IA refactorisant du code legacy dans un rendu 3D glossy et épuré.

Le code PHP legacy, ce doux mélange de fonctions dépréciées, de logique spaghetti et de commentaires en français qui datent de l'époque où PHP 5.3 était le futur. On a tous un de ces projets qui traîne, une vieille application qui tourne encore en production, mais qu'on ose à peine regarder. La refactorer ? Un cauchemar, une perte de temps potentielle énorme. Et si les LLM pouvaient changer la donne ?

J'ai décidé de me plonger dans l'expérimentation, armé de mon homelab et de quelques modèles locaux, pour voir si ces assistants de code dopés à l'IA pouvaient réellement dépoussiérer nos vieux projets PHP sans tout casser. Et comment dire, c'est prometteur, mais pas tout simple non plus...

Pourquoi les LLM pour le refactoring ? Entre promesse et réalité

L'idée d'un agent IA capable de lire votre vieux code, de comprendre ses intentions (même si elles sont obscures) et de le réécrire proprement pour PHP 8.x, c'est tentant. Plus de `mysql_query`, plus de fonctions globales qui font 300 lignes, plus de boucles imbriquées à l'infini… Le rêve, non ?

Mais attention, la réalité est plus nuancée. Une étude très pertinente, "When Modernization Breaks Working Code: A Single-File Study of LLMs on Legacy PHP" (Afridi Mahmud et al., 29 octobre 2026), a mis les pieds dans le plat. Leur conclusion est claire : les LLM, laissés à eux-mêmes, ont souvent tendance à casser le code fonctionnel. Le meilleur LLM testé a laissé seulement 59 fichiers fonctionnels sur 83 qui l'étaient initialement, alors que l'outil basé sur des règles Rector n'en a cassé que 7. La plupart des régressions venaient de déclarations de type rejetées par PHP, ou de modifications inutiles.

Ce n'est pas pour décourager, au contraire ! Ça nous donne des pistes précieuses : les LLM ne sont pas une baguette magique. Ils sont un outil puissant, mais qui demande à être guidé, contrôlé et surtout, testé. L'objectif n'est pas de remplacer le développeur, mais de l'assister sur les tâches répétitives ou de lui proposer des pistes qu'il n'aurait pas envisagées.

Mon setup : Ollama, un modèle local et un agent au service du code

Pour cette expérimentation, j'ai misé sur une approche locale pour des raisons de confidentialité, de coût et de flexibilité. Pour cette fois j'utilise Ollama, qui permet d'exécuter des LLM directement sur ma machine (un petit serveur avec une carte NVIDIA d'occasion).

1. Installer Ollama

C'est d'une simplicité enfantine. Sur Linux, une ligne de commande et le tour est joué :

curl -fsSL https://ollama.com/install.sh | sh

Pour macOS ou Windows, il y a des installateurs graphiques ou des ZIP CLI sur le site officiel.

2. Choisir et télécharger un modèle

J'ai testé plusieurs modèles, mais pour le refactoring, j'ai trouvé que des modèles comme Nemotron 3.5 Lightning de NVIDIA ou Qwen 3.5 étaient particulièrement performants, notamment grâce à leurs capacités agentiques ou leur grande fenêtre de contexte. Pour les besoins de l'article, partons sur Nemotron 3.5 Lightning, que j'ai trouvé plus à l'aise avec les tâches de code complexes. (Cela dit c'est aussi un test donc j'ai pas trop de recul, et pour tout dire la premiere fois que je l'ai utilisé, je l'ai trouvé mauvais).

ollama pull nemotron-3.5-lightning

Si vous avez une carte avec 24GB de VRAM, la version oamazonasgabriel/nemotron-3.5-lightning:q4-24gbGPU est aussi une option intéressante.

3. L'agent : Claude Code via Ollama

Un LLM seul, c'est bien. Un agent qui peut interagir avec votre système de fichiers, éditer du code et exécuter des commandes, c'est mieux. C'est là que Claude Code (l'outil CLI d'Anthropic) entre en jeu, mais connecté à mon Ollama local.

D'abord, installez Claude Code (les instructions sont sur le site d'Anthropic ou d'Ollama) :

curl -fsSL https://claude.ai/install.sh | bash

Ensuite, le petit hack pour le faire pointer vers Ollama. Il suffit de définir quelques variables d'environnement dans votre terminal ou votre script :

export ANTHROPIC_AUTH_TOKEN=ollamaexport ANTHROPIC_API_KEY=""
export ANTHROPIC_BASE_URL=http://localhost:11434

Et maintenant, je peux lancer Claude Code en lui disant d'utiliser mon modèle Nemotron local :

ollama launch claude --model nemotron-3.5-lightning

Une alternative tout aussi intéressante est OpenJarvis, un framework d'agents open-source qui s'intègre nativement avec Ollama et propose un preset code-assistant. Pour les tâches de refactoring, je configure son ~/.openjarvis/config.toml avec default_model = "qwen3.5:35b" pour bénéficier d'une meilleure capacité.

Scénario pratique : Dépoussiérer une fonction PHP à l'ancienne

Prenons un exemple concret. J'ai un vieux script qui gère l'enregistrement d'utilisateurs. La fonction d'enregistrement est un classique du genre : pas de typage, des requêtes SQL directes, et une gestion d'erreur… inexistante.

Avant (le code legacy)

<?php
function registerUser($username, $password, $email) {  
  global $db_connection; // Beurk! 
  if (!isset($db_connection)) {     
    die("Database connection not established!");  
  }  
  $username = mysqli_real_escape_string($db_connection, $username);   
  $password_hash = password_hash($password, PASSWORD_DEFAULT);  
  $email = mysqli_real_escape_string($db_connection, $email); 
  $query = "INSERT INTO users (username, password_hash, email, created_at) VALUES ('{$username}', '{$password_hash}', '{$email}', NOW())"; 
   if (mysqli_query($db_connection, $query)) {   
     return true;  
   } else {   
     echo "Error: " . mysqli_error($db_connection);      
     return false; 
   }
}
?>

Mon prompt

J'ai ouvert Claude Code et lui ai donné le fichier, puis un prompt simple et direct :

"Refactor this PHP function registerUser. Modernize it to use PDO for database interaction, add type hints for parameters and return values, and implement proper exception handling. Ensure the password hashing remains secure with password_hash. The function should return true on success and throw an exception on failure."

Après (le code refactoré par l'agent)

Après quelques secondes de moulinage (qui dépendent de la puissance de votre machine), voici ce que l'agent m'a proposé :

<?php
class UserRegistrationException extends Exception {
}
function registerUser(string $username, string $password, string $email, PDO $pdo): bool
{ 
  try {
    $passwordHash = password_hash($password, PASSWORD_DEFAULT);    
    $stmt = $pdo->prepare( 
      "INSERT INTO users (username, password_hash, email, created_at) VALUES (:username, :password_hash, :email, NOW())"
     );        
    $stmt->bindParam(':username', $username);      
    $stmt->bindParam(':password_hash', $passwordHash);     
    $stmt->bindParam(':email', $email);     
    $stmt->execute();      
    return true;
  } catch (PDOException $e) {  
      throw new UserRegistrationException("Failed to register user: " . $e->getMessage(), 0, $e);  
  }
}
?>

C'est propre ! On a des typages, une injection de dépendance pour PDO, des requêtes préparées, et une gestion d'exception. C'est exactement ce que j'attendais d'un développeur humain, mais en quelques secondes.

Les pièges à éviter et les limites des agents de refactoring

Mon exemple était simple, mais dans la vraie vie, les choses se corsent. L'étude mentionnée plus haut n'est pas là pour rien. Voici ce que j'ai appris :

  • Les "breaks working code" sont réels : L'agent peut introduire des bugs subtils, des régressions fonctionnelles. Il faut toujours, toujours, TOUJOURS tester le code généré. Des tests unitaires existants sont une bénédiction. Sinon, c'est l'occasion d'en écrire !
  • Contextes limités : Même avec des modèles à grande fenêtre de contexte, donner un fichier de 5000 lignes ou un projet entier en une fois est une recette pour l'hallucination ou des réponses incomplètes. Divisez le travail en petites fonctions, en petits fichiers.
  • Hallucinations et fausses bonnes idées : L'agent peut inventer des fonctions qui n'existent pas, utiliser des syntaxes non supportées par votre version de PHP, ou proposer des solutions qui semblent élégantes mais sont incorrectes. Vérifiez tout.
  • Dépendance aux prompts : La qualité du refactoring dépend énormément de la clarté et de la précision de votre prompt. Soyez explicite sur ce que vous voulez.
  • Pas de compréhension métier profonde : Un LLM ne comprend pas le "pourquoi" derrière une logique métier complexe. Il ne faut pas lui demander de réécrire des règles métier sans supervision humaine.

Conseils et bonnes pratiques pour intégrer les LLM dans votre workflow

Pour tirer le meilleur parti de ces outils sans introduire de chaos dans votre codebase :

  • Commencez petit : Ne refactorez pas tout un module d'un coup. Prenez une petite fonction isolée, un fichier, et validez le processus.
  • Tests, tests, tests : C'est la ligne de défense la plus importante. Si vous n'avez pas de tests automatisés, c'est le moment d'en créer pour chaque morceau de code que vous confiez à l'IA.
  • Version Control FTW : Utilisez Git (ou autre) et faites des commits réguliers. Comparez les diffs avec attention. Rejetez sans hésiter si le changement est trop risqué ou incompréhensible.
  • Combine with rule-based tools : Pour les modernisations simples et répétitives (comme les changements de syntaxe pour PHP 8.x), des outils comme Rector restent plus fiables et rapides. Utilisez les LLM pour les refactorings plus complexes, qui demandent une compréhension contextuelle.
  • Prompt engineering : Passez du temps à affiner vos prompts. Donnez des exemples, précisez la version de PHP cible, les standards de codage (PSR) à respecter.

Conclusion : Un gain de temps réel ? Perspectives futures.

Alors, est-ce un gain de temps réel ? Oui, absolument, mais avec un grand "si" : si vous avez une stratégie claire, des tests solides et une supervision humaine rigoureuse. Pour les tâches de refactoring répétitives ou pour explorer rapidement des options de modernisation, les agents LLM sont incroyablement efficaces. Ils peuvent vous faire gagner des heures à écrire du code boilerplate ou à chercher des patterns de refactoring.

Le futur est prometteur. Avec des modèles toujours plus performants, des agents plus autonomes et des intégrations plus poussées (comme le travail de Symfony sur Symfony AI et le SDK MCP qui vise à standardiser l'interaction avec les LLM), le refactoring de code PHP legacy pourrait devenir une tâche beaucoup moins redoutable. Mais pour l'instant, gardons les mains sur le volant et les yeux rivés sur le diff !

Publié le 04/11/2026 · 8 min de lecture Partager X LinkedIn

← Précédent Composer 2.11 et la cooldown policy : quand vos dépendances apprennent à patienter pour des déploiements sereins