Common causes
- The variable is only assigned inside an if, loop or try block that did not run
- A function uses a variable from outside without passing it as a parameter
- A closure uses an outer variable without a use ($var) clause
- A typo or case difference ($Total vs $total)
- Template files expecting variables that the caller did not pass
- Old code relying on register_globals, which was removed long ago
How to fix it
- Initialise the variable first. Set a default before any condition, for example $total = 0; at the top. Then the variable exists whichever branch runs.
- Pass values into functions. Functions in PHP cannot see outer variables. Add a parameter, such as function render($total), and pass the value when calling it.
- Add use() to closures. For anonymous functions write function () use ($total) { ... }, or use an arrow function fn() => $total * 2, which captures outer variables automatically.
- Check spelling and case. Variable names are case-sensitive. Search the file for the name to confirm it is spelled the same everywhere.
- Pass data to templates explicitly. In WordPress use get_template_part('card', null, ['post' => $post]) and read $args['post'] inside the template, rather than expecting a variable to exist.
Initialise before conditions and capture in closures
$total = 0;
foreach ($items as $item) {
$total += $item['price'];
}
$withTax = array_map(fn($p) => $p * $rate, $prices);
$log = function ($msg) use ($logger) { $logger->info($msg); }; How to stop it happening again
- Declare variables with defaults at the top of each block
- Avoid global variables; pass data as parameters
- Use a static analyser such as PHPStan to catch undefined variables
- Develop with error_reporting(E_ALL) and display_errors on