PHP / Editorial solution guide
Undefined keys, TypeError, and missing classes
Classify a failure before changing code or dependencies. Trace request shape, type contracts, namespaces, and autoload paths using small synthetic evidence.
Read-only knowledge base ยท No public comments
Recognize the symptoms
A request sometimes emits an undefined-array-key warning, a typed call rejects a value, or a class cannot be found from a clean entry point. These can appear together when earlier code assumes a record shape or bootstrap state that exists only on one machine. Preserve the exact first diagnostic and the smallest triggering input.
Understand the likely causes
- Typical causes are missing versus null confusion, an array supplied where a scalar was expected, a missing return, a namespace alias mistaken for loading, a PSR-4 case mismatch, or an unloaded generated autoloader. Suppressing warnings or running a broad dependency update can conceal the initial boundary failure without repairing its contract.
1. Separate the mechanism and the violated assumption
Identify warning, TypeError, or class-loading failure rather than labeling everything an exception. Inspect a safe summary of the value immediately before the failing access or call: type, required-key presence, and a synthetic identifier. Do not log the full request, passwords, or session data. A missing key needs a presence policy; a wrong scalar needs parsing; a missing class needs naming/loading evidence. Start at the first invalid step so later symptoms do not drive unrelated fixes.
2. Restore the input and absence contract
Use array_key_exists when explicit null must differ from absence, and use null coalescing only when that fallback is genuinely allowed. Validate whether a field is a scalar before string or numeric operations. The example preserves a valid zero and distinguishes a present null note from a missing key. A fallback empty array is not a repair for a required record. Trace a missing function return to its source instead of making every caller accept undefined state as normal.
<?php
declare(strict_types=1);
$input = ["count" => 0, "note" => null];
echo $input["count"] ?? 10, PHP_EOL;
echo array_key_exists("note", $input) ? "present
" : "missing
";
echo isset($input["note"]) ? "non-null
" : "null-or-missing
";
0
present
null-or-missing
The example produces no undefined-key warning and does not replace valid zero with a default.
3. Repair the typed boundary rather than disabling it
Compare the declared parameter and return contract with the actual caller value. Under strict scalar calling rules, a numeric-looking request string can still be the wrong type; parse and validate at the adapter before calling the domain function. Do not remove a useful declaration merely to accept malformed input. Distinguish expected user rejection from a programmer defect and keep failure categories visible. If the code uses syntax newer than the runtime, a type cast cannot repair parser compatibility; inspect the actual CLI or web binary and documented minimum version.
4. Diagnose class discovery without mutating dependencies blindly
Record the fully qualified requested name, declared namespace/class, mapped directory and filename case, and whether the entry point included the intended autoloader. A use statement changes naming, not loading. Inspect composer.json and the lock as read-only evidence; regenerate metadata through the project workflow when the mapping changed, but do not edit vendor files or run an update to fix a typo. A class declared in one already-loaded test file does not prove clean-entry autoload integration. Keep that check separate from pure language tests.
Verify the fix
Verify absent, null, valid zero, wrong scalar, and array-shaped inputs independently. Then check a clean isolated entry point resolves the expected class with exact case and required platform capabilities. Confirm the original diagnostic disappears for the right reason and malformed input receives the intended safe rejection rather than an unrelated error.
Keep it from recurring
- Validate external records once, document nullability, keep typed function contracts, and test return paths. Align namespace/file conventions and lock dependency intent. Avoid @ suppression and broad updates as default troubleshooting; retain a minimal reproducer with runtime and loader assumptions.