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: PHPIntroduction
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.
.avif)
