After moving a site from PHP 7.4 to 8.3 the logs are full of "Warning: Undefined array key "name"" and "Warning: Undefined variable $total". It used to be a notice I ignored. What is the right fix?
DEV3 Developer Forum
What do 'Undefined array key' and 'Undefined variable' warnings mean in PHP 8 and how do I fix them?
Every post is reviewed first. Usually reviewed within 24 hours.
1 reply
PHP 8 promoted these from notices to warnings (and "Undefined offset/index" was unified to "Undefined array key"). The code was always buggy; PHP now tells you. Fix the cause instead of lowering error reporting.
Undefined array key
// before
$name = $_POST['name'];
// null coalescing: default when missing or null
$name = $_POST['name'] ?? '';
// check explicitly
if (array_key_exists('name', $row)) {}
if (isset($row['name'])) {} // false if the key exists but is null
??= assigns a default when missing: $config['debug'] ??= false;.
Undefined variable
$total = 0; // initialise before loops and conditionals
foreach ($items as $i) { $total += $i['price']; }
Typical cause: a variable assigned only inside an if branch, or a typo. Use static analysis: phpstan analyse -l 5 src finds them all.
Related PHP 8 changes you may meet when upgrading
Attempt to read property "x" on null: use the nullsafe operator$user?->profile?->name.Deprecated: Creation of dynamic property(PHP 8.2): declare the property in the class, use#[AllowDynamicProperties]only as a stop-gap, orstdClass.- Passing
nullto non-nullable internal function parameters is deprecated in 8.1 (strlen(null),trim(null)); cast or default:trim($s ?? ''). ${var}string interpolation is deprecated in 8.2; use{$var}or$var.- Implicit float to int loss in array keys is deprecated in 8.1.
Do not use @ or error_reporting(0)
The @ suppression operator hides real errors and is slow. Keep E_ALL in development and log in production (see the PHP error reporting topic).
Tools for large upgrades: Rector with the PHP 8 set rules, php -l for syntax, and PHPCompatibility for PHP_CodeSniffer. Run your tests on both versions during the migration.