The fix depends on the update contract. Decide that contract before replacing one presence check with another.
Define the update using actual before-and-after values
In this original exercise, a profile begins with display_name set to Morgan. A request is already represented as a PHP associative array. Its permitted update field has four meaningful cases:
| Supplied update | Resulting display name |
|---|---|
[] |
Morgan |
['display_name' => null] |
null |
['display_name' => ''] |
Empty string |
['display_name' => 'Mo'] |
Mo |
This exercise intentionally permits an empty string. Whether a real product should allow one is a separate policy decision. A number, boolean, array or object is rejected for this field.
Apply the presence check before reading the value
Save this authored PHP 8 example as profile-update.php:
<?php
declare(strict_types=1);
function applyDisplayName(array $current, array $update): array {
if (array_key_exists('display_name', $update)) {
$value = $update['display_name'];
if ($value !== null && !is_string($value)) {
throw new InvalidArgumentException('display_name must be string or null');
}
$current['display_name'] = $value;
}
return $current;
}
$current = ['display_name' => 'Morgan'];
$cases = [
'omitted' => [],
'clear' => ['display_name' => null],
'empty' => ['display_name' => ''],
'replace' => ['display_name' => 'Mo'],
];
foreach ($cases as $label => $update) {
$result = applyDisplayName($current, $update);
echo $label . ': ' . json_encode($result['display_name']) . PHP_EOL;
}
With PHP installed, check php --version, then run php profile-update.php. Expected output:
omitted: "Morgan"
clear: null
empty: ""
replace: "Mo"
The PHP manual for array_key_exists, checked October 24, 2026, distinguishes an existing null-valued key from an absent key. isset($update['display_name']) would fail to enter the branch for the clear case. A null-coalescing default would also merge those two meanings.
This function returns a new array value for the caller to use; it does not save a database record or authorize a profile change. It changes only the named field and leaves other current fields alone. Other incoming fields are ignored in this small example. Define an explicit unknown-field policy in a real request boundary rather than assuming this function validates a whole payload.
Give ChatGPT the transition table
Review this PHP partial-update function.
PHP version and complete function/caller: [PASTE]
Input has already been decoded to an associative array.
Before value and required cases: [PASTE THE TRANSITION TABLE]
Omitted display_name must preserve the old value. Present null must
clear it. Present empty string is allowed. Other string values replace
it; other types must be rejected. Do not use truthiness, isset or ??
to merge absent and null. Update only the named field and return the
array without writing storage. Explain unknown-field handling.
Return expected outputs and a wrong-type rejection check.
Do not add authentication, database access or claim execution.
If input is decoded as an object instead, do not pass it to this array function unchanged. Establish that boundary deliberately. The API documentation guide explains presence and null in a schema; this function must additionally preserve their different effects on existing state. Check the returned values and wrong-type rejection locally before connecting the accepted behavior to authorized storage.