Aikido

Why you should avoid dynamic variable names in PHP

Readability

Rule
Avoid dynamic variable names
Dynamic variable names (variable variables) can lead
to hard to maintain code and unexpected behaviour. 
Their usage is usually the result of a typo.

Supported languages: PHP

Introduction

PHP's variable variables feature lets you use one variable's value as another variable's name with the $$ syntax. What looks like a clever shortcut becomes a debugging nightmare when you can't statically determine which variables exist or what they contain. Code that uses $$userName instead of an array or object property makes it impossible for IDEs to provide autocomplete, for static analyzers to catch bugs, or for developers to trace data flow through the application.

Why it matters

Code maintainability: Variable variables break every tool developers rely on. IDEs can't autocomplete variable names, find usages, or refactor safely. Static analysis tools can't detect undefined variables or type mismatches. Debugging requires runtime inspection because you can't grep the codebase to find where variables are set or read.

Security implications: When variable variable names come from user input, attackers can overwrite arbitrary variables including security-critical ones. A malicious request parameter could target $$_GET['var'] to overwrite $isAdmin, $userId, or session variables. This creates variable injection vulnerabilities that are difficult to detect and easy to exploit.

Performance impact: Variable variables force PHP to perform runtime lookups instead of compile-time symbol resolution. The interpreter must evaluate the variable name dynamically on every access, preventing optimizations that work with normal variables. Arrays and objects provide similar functionality with better performance characteristics.

Code examples

❌ Non-compliant:

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');

Why it's wrong: The code creates $userForm or $adminForm dynamically using $$formName, making it impossible to trace which variable is being modified. If $formType comes from user input, attackers could inject arbitrary variable names to overwrite critical variables.

✅ Compliant:

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');

Why this matters: The code uses an explicit array with known keys, making data flow obvious and enabling all IDE features. Input validation prevents injection attacks, and static analysis can verify the code is correct.

Conclusion

Replace variable variables with arrays, objects, or better code structure. Use arrays when you need dynamic key access, use objects for structured data with known properties, and refactor duplicated logic into proper abstractions. Variable variables almost always indicate a design problem that proper data structures would solve more clearly.

FAQs

Got Questions?

Are there any legitimate uses for variable variables?

Extremely rare. Template engines and metaprogramming frameworks sometimes use them, but even those cases are better served by arrays or dedicated data structures. If you think you need variable variables, you probably need an array with dynamic keys or a redesign of your data flow.

What about extract() which creates variables dynamically?

Avoid extract() for the same reasons as variable variables. It creates variables from array keys dynamically, breaking static analysis and creating security risks. Use array access directly: $data['key'] instead of extract($data); $key. Modern PHP code should treat extract() as a code smell.

How do I refactor existing code that uses variable variables?

Identify the pattern being implemented. Usually it's either configuration data (use arrays), dynamic properties (use objects or arrays), or conditional logic (use proper control structures). Replace $$varName with $config[$varName] for most cases. Use objects when you need type safety and IDE support for property access.

What about using variable variables for constants?

Still problematic. Use constant($name) if you must dynamically access constants, though this also suggests a design issue. Better approach: organize related constants in a class and use an array or match expression to select the appropriate value based on runtime conditions.

Can variable variables cause namespace collisions?

Yes, especially with superglobals and framework variables. Code using $$type = 'value' could accidentally create $_GET, $_POST, or framework variables like $this in unexpected contexts. Arrays naturally namespace their data, preventing these collisions by design.

Get secure now

Secure your code, cloud, and runtime in one central system.
Find and fix vulnerabilities fast automatically.

No credit card required | Scan results in 32secs.