€0.00 — free as in speechtonight's forecast: clear skies over production Cache: warm · Deploys: fair, 0% rollbacks expectedset by moonlight, shipped before dawn · deploy freely Page A2

❦The Daily Commit❦ ☾The Nightly Build☽

Dev news, typeset daily — PHP · AI · The Wider Stack

The developer's evening paper — PHP · AI · The Wider Stack

Monday, November 9, 2026 Vol. I — No. 895 · Morning editionLate edition EN DE FR ES

PHP · RFC Watch

PHP pattern matching debate turns on keys and ints

Kevin Lopez has raised two semantic issues in the draft PHP Pattern Matching RFC.

curated by Sönke

Array patterns should distinguish a missing key from an explicit null and use array_key_exists(). Integer patterns and numeric ranges should reject strings and floats, even when their values fit. Lopez says these rules are required to validate model JSON with exact fields and types.

Kevin Lopez addressed Larry and Ilija in a PHP Internals discussion about the draft Pattern Matching RFC. He maintains a production PHP application that rejects a model's JSON response when a field is missing or has the wrong type. Lopez says the current draft could accept two responses that this application must reject.

partQuote.php
<?php
function partQuote(array $p): ?array {
 if (!is_string($p['part'] ?? null)) {
 return null;
 }
 if (array_key_exists('quote', $p) && $p['quote'] !== null && !is_string($p['quote'])) {
 return null;
 }
 $out = ['part' => $p['part']];
 if (array_key_exists('quote', $p)) {
 $out['quote'] = $p['quote']; // null is kept; the key was present
 }
 return $out;
}

The RFC's array-pattern rules use array_key_exists() before comparing a value. An implementation note in php/php-src pull request 20574 says the draft reads a missing element as null. That would make `['a' => 42]` match `['b' => null]`. Lopez asks the authors to keep the existing RFC wording because his parser treats an absent key and a present key containing null as different states.

His `partQuote()` example requires `part` to be a string. `quote` may be absent, null, or a string, but another type returns null. The output keeps the `quote` key when it was supplied. As a result, `partQuote(['part' => 'A'])` returns `['part' => 'A']`. A call with `quote` set to null keeps that key in the output. A numeric quote returns null.

The second issue concerns a score-like field. The parser requires `strength` to pass is_int() before applying the inclusive 0 through 100 range. `'80'` fails because it is a string, and `80.0` fails because it is a float. `101` is outside the range. For `relevant`, the same no-coercion rule uses is_bool(): both `1` and `'true'` fail. `strength` 80 together with `relevant` true passes. Lopez says an int pattern and a range pattern such as `>=0 & <=100` must reject numeric strings and floats when used for this field. He is asking for the existing rules to be applied consistently, not for new syntax.

Read the original source ↗

Rate this article: 0

Readers’ Forum

No contributions yet — open the debate.

← The Daily CommitThe Nightly Build — Page A1