After moving to PHP 8, your logs may start showing Undefined array key warnings. Often the code assumes that every request contains a field that is actually optional. Before suppressing the warning, decide whether the key is absent, present with a null value, or present with an empty string. Those states can mean different things to the application.
Missing, null and empty are different inputs
A form field omitted from a request may not exist in $_POST. A submitted but blank field is commonly an empty string. A JSON payload can explicitly contain null. Collapsing all three into one default can have an unintended effect—for example, clearing a stored value when the client meant to leave it unchanged.
// Use a default when the key is absent or null.
$page = $_GET['page'] ?? 1;
// Test key presence even if its value may be null.
$hasLimit = array_key_exists('limit', $options);
// Treat null as missing and use a default.
$limit = isset($options['limit']) ? (int) $options['limit'] : 20;
?? and isset() treat a null value like a missing key. array_key_exists() checks whether the key exists, so it returns true even when the value is null. The right choice depends on what the field means, not on which expression is shortest.
For example, in a settings form an omitted field might mean “leave unchanged,” while an explicitly blank field might mean “clear this value.” Using ?? '' for both loses that distinction. Decide in the API or form contract whether a missing property and a null property should have different meanings.
Validate the source and the expected shape
If a field is required, a default may be the wrong fix; report a validation error instead. Check the request method and content type, then validate the value's type and allowed range. PHP's filter_input() can read external input through a filter, but its behavior and common reasons for returning null are covered separately in why PHP filter_input() returns NULL.
PHP 8's migration notes describe the change in visibility for some undefined-key accesses. That does not mean every warning is only a version issue: trace where the field comes from and what the client is required to send. See the official PHP 8 migration notes and array_key_exists() reference.