Aller au contenu principal

Refactoring de code PHP dans VSCode

Maîtrisez le refactoring de code PHP dans VSCode avec ce guide. Utilisez l'extension gratuite PHP Refactor Tool pour renommer sans risque symboles et classes, et extraire de nouvelles méthodes.

· 7 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Cet article a plus d'un an, mais il a été relu le 30 juillet 2026 — son contenu est toujours exact.

Refactoring de code PHP dans VSCode

⚡
TL;DR

Cet article traite du refactoring PHP dans VSCode avec les extensions gratuites PHP Refactor Tool et PHP Refactoring : renommer un symbole ou une classe avec F2 (ce qui met à jour automatiquement chaque utilisation dans tous les fichiers) et extraire un bloc de code vers une nouvelle méthode, avec détection automatique des variables locales qui doivent devenir des paramètres.

Actuellement, fin février 2024, il n'existe pas beaucoup d'extensions de refactoring gratuites pour PHP sous VSCode. Nous allons regarder PHP Refactor Tool et PHP Refactoring.

Nous allons apprendre à renommer un symbole, une classe et, encore mieux, à extraire une portion d'une longue méthode vers une nouvelle.

Ces extensions refactorisent ce que vous leur désignez. Pour des refactorings suggérés — et appliqués — automatiquement sur tout un code source, voir Rector 1.0.0, my friend, my coach.

Créer les fichiers d'exemple​

Pour la démo, lancez un shell Linux et exécutez mkdir -p /tmp/refactor && cd $_ pour créer un dossier refactor dans votre dossier temporaire Linux et vous y rendre.

Créez deux fichiers php. Le premier s'appellera index.php et contiendra ce code :

<?php
namespace Cavo;
require_once('Product.php');
$product = new Product();
$product->setProductName('keyboard');
$product->setProductPrice(125);
printf(
'The name is %s cost %d €'.PHP_EOL,
$product->getProductName(),
$product->getProductPrice()
);

Ce script instancie un objet Product, configure son nom et son prix via des méthodes setter, puis affiche les informations du produit formatées avec printf. C'est un exemple basique de création et d'utilisation d'une classe.

Le second fichier, Product.php, contiendra :

<?php
namespace Cavo;
class Product
{
private string $productName = '';
private float $productPrice = 0;
public function __construct(string $name='', float $price=0)
{
$this->setProductName($name);
$this->setProductPrice($price);
}
public function getProductName(): string {
return $this->productName;
}
public function setProductName(string $name): void {
$this->productName = $name;
}
public function getProductPrice(): float {
return $this->productPrice;
}
public function setProductPrice(float $price): void {
$this->productPrice = $price;
}
}

Cette classe Product représente un produit avec un nom et un prix. Elle encapsule ces deux propriétés privées et fournit des méthodes publiques pour les lire et les modifier, ainsi qu'un constructeur pour initialiser l'objet avec des valeurs par défaut.

Lancer l'exemple​

Exécutez docker run -it --rm -v "${PWD}":/project -w /project php:8.2 php index.php pour lancer notre exemple dans la console.

Vous obtiendrez, comme prévu :

>user@machine: ~/yourproject

Refactoring​

Assurez-vous que PHP Refactor Tool est installé. Allez dans la liste des extensions de VSCode (appuyez sur CTRL-SHIFT-X) et recherchez PHP Refactor Tool. Installez celle de Son Tung PHAM (l'auteur).

Renommer un symbole​

L'illustration ci-dessous montre un script index.php d'exemple utilisant une classe définie dans Product.php.

Tout fonctionne bien mais, oui, les fonctions s'appellent getProductName et getProductPrice et c'est assez redondant : notre objet est $product donc, oui, $product->getProductName() et $product->getProductPrice() peuvent être réécrits en $product->getName() et $product->getPrice(). Plus court, c'est mieux.

Nous devons donc renommer nos fonctions.

En ouvrant notre fichier Product.php, nous pourrions le faire à la main mais... ne faites pas ça : vous devriez mettre à jour manuellement chaque fichier utilisant votre classe Product et si vous oubliez ne serait-ce qu'une utilisation, votre code sera cassé.

La fonctionnalité de renommage sert exactement à ça. Il vous suffit de sélectionner une propriété comme productName comme illustré dans l'animation, d'appuyer sur F2 et de la renommer.

Faisons-le et voyons comment ça fonctionne :

  1. Ouvrez le fichier Product.php, placez le curseur sur le mot productName à la ligne 7 private string $productName = '';,
  2. Appuyez sur F2 (ou choisissez Rename Symbol dans la palette de commandes (appuyez sur CTRL-SHIFT-P)) et tapez le nouveau nom, par exemple name (au lieu de productName),
  3. VSCode affichera une petite liste en haut de l'écran, validez simplement, c'est-à-dire sélectionnez Update Getter name and Setter name.
  4. Faites de même pour productPrice et renommez-le en price.

Le nouveau fichier Product.php est maintenant :

<?php
namespace Cavo;
class Product
{
private string $name = '';
private float $price = 0;
public function __construct(string $name='', float $price=0)
{
$this->setName($name);
$this->setPrice($price);
}
public function getName(): string {
return $this->name;
}
public function setName(string $name): void {
$this->name = $name;
}
public function getPrice(): float {
return $this->price;
}
public function setPrice(float $price): void {
$this->price = $price;
}
}

Ceci définit une classe Product dans l'espace de noms Cavo qui représente un produit avec un nom et un prix. La classe utilise des propriétés privées avec des getters et setters publics pour contrôler l'accès à ces données, et initialise ces propriétés via un constructeur.

Mais le plus sympa, c'est que index.php a été mis à jour automatiquement. Ouvrez index.php et vérifiez :

<?php
namespace Cavo;
require_once('Product.php');
$product = new Product();
$product->setName('keyboard');
$product->setPrice(125);
printf(
'The name is %s cost %d €'.PHP_EOL,
$product->getName(),
$product->getPrice()
);

Ce script instancie une classe Product, configure ses propriétés (nom et prix) via des setters, puis affiche le produit formaté avec printf en utilisant les getters correspondants.

En exécutant docker run -it --rm -v "${PWD}":/project -w /project php:8.2 php index.php, ça fonctionne toujours.

Vous avez refactorisé notre code sans le casser. Félicitations !

La même chose en images :

Renommer un symbole

Renommer une classe​

Pour l'exemple, réouvrez le fichier Product.php et, à la ligne 5, placez le curseur sur le mot Product. Appuyez sur F2 et renommez en Products (au pluriel).

Comme on pouvait s'y attendre, le nom de la classe a été mis à jour, mais le nom du fichier aussi. Et, une fois encore, si vous ouvrez le fichier index.php, vous verrez que $product = new Product(); est devenu parfaitement $product = new Products();.

Renommer une classe

Vous pouvez aussi renommer depuis index.php

Repérez la ligne $product = new Product(); dans votre fichier index.php. Placez le curseur sur le mot Product, appuyez sur F2 et renommez-le. Ça fonctionne aussi, c'est-à-dire que la classe sera également mise à jour dans Products.php (puisque le fichier a été renommé lui aussi). Sympa !

Renommer une classe

Ne renommez pas le fichier

Renommer le fichier depuis l'explorateur ne refactorisera pas le code. Donc, n'allez pas dans l'Explorer, cliquer sur Product.php et le renommer. Cela ne refactorisera pas le code. À éviter !

Extraire vers une nouvelle méthode​

La troisième méthode très pratique est Extract method de PHP Refactoring.

Prenons l'exemple suivant (le code ne tourne pas, c'est juste pour l'illustration). Créez un nouveau fichier appelé Pandoc.php avec ce contenu :

<?php
namespace Avonture;
class Pandoc
{
public function download(string $filename): void
{
$filename = Sanitize::sanitizeFileName(trim($filename));
if ('' == $filename) {
throw new PandocFileNotSpecified();
}
if (!is_file($this->outputFolder . $filename)) {
throw new PandocFileNotFound($filename);
}
// Make the filename absolute
$filename = $this->outputFolder . ltrim($filename, self::DS);
$this->outputType = pathinfo($filename)['extension'];
$contentType = $this->getContentType()['type'];
header('Content-Type: ' . $contentType);
header('Content-Transfer-Encoding: ' . $this->getContentType()['encoding']);
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Content-Length: ' . filesize(utf8_decode($filename)));
header('Accept-Ranges: bytes');
header('Pragma: no-cache');
header('Expires: 0');
ob_end_flush();
@readfile(utf8_decode($filename));
}
}

Cette méthode gère le téléchargement d'un fichier généré par Pandoc. Elle valide le nom de fichier, vérifie que le fichier existe, puis configure les en-têtes HTTP appropriés avant d'envoyer le contenu du fichier au navigateur.

La fonction download ne respecte pas le principe de responsabilité unique. Nous y faisons quelques initialisations et assertions. Peut-on faire mieux ? Oui : nous pouvons extraire les lignes concernant le navigateur et créer une nouvelle fonction sendToBrowser mais, au lieu de le faire à la main, nous allons utiliser la fonctionnalité Extract.

Voyez l'animation ci-dessous :

Extraire vers une nouvelle méthode

Avez-vous remarqué l'usage des paramètres d'entrée ?

Dans les lignes que nous déplaçons, il y a des variables comme contentType et filename qui ne font pas partie de la nouvelle méthode. Ces variables restent locales à notre première méthode, download.

Et, comme vous pouvez le voir, lors de la création de la nouvelle méthode, ces deux variables locales ont été ajoutées à la définition de la nouvelle fonction. Très bonne fonctionnalité.

Autres extensions​

  • 💀 😒 PHP Refactor existe également mais la dernière mise à jour par l'auteur date de 2019, il y a cinq ans, et la fonctionnalité d'extraction ne fonctionne pas bien ; passez votre chemin.
  • 💲😒 PHP Tools for Visual Studio Code de DEVSENSE est une extension freemium (les fonctionnalités de refactoring ne sont que dans la version payante). Le renommage de symbole est payant alors qu'il est gratuit avec PHP Refactor Tool. N'installez pas PHP Tools for Visual Studio Code car il écrasera la fonction F2 de PHP Refactor Tool et la cassera. (voir mon issue Devsense - All-In-One conflicts)

Renommer et extraire des méthodes n'est qu'une partie du travail pour garder un code PHP sain ; pour l'analyse statique et le formatage automatisés, voir l'image Docker regroupant des outils d'analyse statique et formater du code PHP mal formaté.


Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?