Aikido

Pourquoi il faut éviter les noms de variables dynamiques en PHP

Lisibilité

Règle
Éviter variable variable noms
Dynamique variables noms (variables variables) peuvent conduire
à difficultés difficile maintenir code et comportement comportement. 
Leur utilisation est généralement le résultat de une faute de frappe.

Langues prises en charge : PHP

Introduction

La fonctionnalité de variables variables de PHP permet d'utiliser la valeur d'une variable comme nom d'une autre variable avec le $$ syntaxe. Ce qui semble être un raccourci astucieux devient un cauchemar de débogage lorsqu'il est impossible de déterminer statiquement quelles variables existent ou ce qu'elles contiennent. Le code qui utilise $$userName au lieu d'une propriété de tableau ou d'objet rend impossible pour les IDEs de fournir l'autocomplétion, pour les analyseurs statiques de détecter les bugs, ou pour les développeurs de tracer le flux de données à travers l'application.

Pourquoi c'est important

Maintenabilité du code : Les variables variables (variable variables) cassent tous les outils sur lesquels les développeurs s'appuient. Les IDE ne peuvent pas auto-compléter les noms de variables, trouver les usages ou refactoriser en toute sécurité. Les outils d'analyse statique ne peuvent pas détecter les variables non définies ou les incompatibilités de type. Le débogage nécessite une inspection runtime car il est impossible de `grep` la base de code pour trouver où les variables sont définies ou lues.

Implications en matière de sécurité : Lorsque les noms de variables dynamiques proviennent de l'entrée utilisateur, les attaquants peuvent écraser des variables arbitraires, y compris celles critiques pour la sécurité. Un paramètre de requête malveillant pourrait cibler $$_GET['var'] écraser $isAdmin, $userId, ou des variables de session. Cela crée des vulnérabilités d'injection de variables difficiles à détecter et faciles à exploiter.

Impact sur les performances : Les variables variables forcent PHP à effectuer des recherches au moment de l'exécution plutôt qu'une résolution de symboles au moment de la compilation. L'interpréteur doit évaluer le nom de la variable dynamiquement à chaque accès, empêchant les optimisations qui fonctionnent avec les variables normales. Les tableaux et les objets offrent des fonctionnalités similaires avec de meilleures caractéristiques de performance.

Exemples de code

❌ Non conforme :

function processFormData($formType) {
    $userForm = ['name' => '', 'email' => ''];
    $adminForm = ['name' => '', 'email' => '', 'role' => ''];

    $formName = $formType . 'Form';
    $$formName = array_merge($$formName, $_POST);

    if ($$formName['email']) {
        sendEmail($$formName['email']);
    }

    return $$formName;
}

// What variable does this actually use?
processFormData('user');

Pourquoi c'est incorrect : Le code crée $userForm ou $adminForm en utilisant dynamiquement $$formName, rendant impossible de tracer quelle variable est modifiée. Si $formType provient de l'entrée utilisateur, les attaquants pourraient injecter des noms de variables arbitraires pour écraser des variables critiques.

✅ Conforme :

function processFormData(string $formType): array {
    $forms = [
        'user' => ['name' => '', 'email' => ''],
        'admin' => ['name' => '', 'email' => '', 'role' => '']
    ];

    if (!isset($forms[$formType])) {
        throw new InvalidArgumentException('Invalid form type');
    }

    $form = array_merge($forms[$formType], $_POST);

    if (!empty($form['email'])) {
        sendEmail($form['email']);
    }

    return $form;
}

// Clear which data structure is being used
processFormData('user');

Pourquoi c'est important : Le code utilise un tableau explicite avec des clés connues, rendant le flux de données évident et activant toutes les fonctionnalités de l'IDE. La validation des entrées prévient les attaques par injection, et l'analyse statique peut vérifier la correction du code.

Conclusion

Remplacez les variables variables par des tableaux, des objets ou une meilleure structure de code. Utilisez des tableaux lorsque vous avez besoin d'un accès dynamique par clé, utilisez des objets pour les données structurées avec des propriétés connues, et refactorisez la logique dupliquée en abstractions appropriées. Les variables variables indiquent presque toujours un problème de conception que des structures de données appropriées résoudraient plus clairement.

FAQ

Des questions ?

Existe-t-il des utilisations légitimes pour les variables variables ?

Extrêmement rare. Les moteurs de template et les frameworks de métaprogrammation les utilisent parfois, mais même dans ces cas, les tableaux ou les structures de données dédiées sont plus appropriés. Si vous pensez avoir besoin de variables variables, vous avez probablement besoin d'un tableau avec des clés dynamiques ou d'une refonte de votre flux de données.

Qu'en est-il de extract() qui crée des variables dynamiquement ?

Évitez extract() pour les mêmes raisons que les variables variables. Cette fonction crée des variables à partir des clés de tableau de manière dynamique, ce qui rompt l'analyse statique et crée des risques de sécurité. Utilisez l'accès direct aux tableaux : $data['key'] au lieu de extract($data); $key. Le code PHP moderne devrait considérer extract() comme un code smell.

Comment refactoriser le code existant qui utilise des variables variables ?

Identifiez le modèle mis en œuvre. Il s'agit généralement de données de configuration (utiliser des tableaux), de propriétés dynamiques (utiliser des objets ou des tableaux) ou de logique conditionnelle (utiliser des structures de contrôle appropriées). Remplacez $$varName par $config[$varName] dans la plupart des cas. Utilisez des objets lorsque vous avez besoin de la sécurité de type et du support de l'IDE pour l'accès aux propriétés.

Qu'en est-il de l'utilisation de variables variables pour les constantes ?

Toujours problématique. Utilisez constant($name) si vous devez accéder dynamiquement à des constantes, bien que cela suggère également un problème de conception. Meilleure approche : organisez les constantes associées dans une classe et utilisez un tableau ou une expression de correspondance pour sélectionner la valeur appropriée en fonction des conditions d'exécution.

Les variables variables peuvent-elles provoquer des collisions de namespace ?

Oui, surtout avec les superglobales et les variables de framework. Le code utilisant $$type = 'value' pourrait accidentellement créer des variables $_GET, $_POST ou des variables de framework comme $this dans des contextes inattendus. Les tableaux organisent naturellement leurs données en espaces de noms, empêchant ces collisions par conception.

Sécurisez-vous maintenant.

Sécuriser votre code, votre cloud et votre runtime dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Pas de carte de crédit requise | Résultats du scan en 32 secondes.