Re: [RFC] Pattern Matching — missing keys and strict int

From: Date: Thu, 22 Oct 2026 12:30:14 +0000
Subject: Re: [RFC] Pattern Matching — missing keys and strict int
Groups: php.internals 
Request: Send a blank email to internals+get-132899@lists.php.net to get a copy of this message
> Hello Larry and Ilija, > > I maintain a production PHP application that rejects a model’s JSON reply unless every field > is present and of an exact type. Pattern matching is the language feature that would replace those > checks. Two outcomes in the current draft would make that replacement accept replies we currently > reject. Both are constraints on the rules you already wrote, not requests for new syntax. > > The RFC’s array-pattern equivalents use array_key_exists() before comparing the value. A > missing key therefore fails the pattern. The implementation note on > https://github.com/php/php-src/pull/20574 says the draft reads a > missing element as null, so this is true: > > ['a' => 42] is ['b' => null] > > Please keep the RFC text. For this parser, a missing key and an explicit null are different > successful results, and a value of any other type is a failure: > > 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; > } > > partQuote(['part' => 'A']); // ['part' > => 'A'] > partQuote(['part' => 'A', 'quote' => null]); // > ['part' => 'A', 'quote' => null] > partQuote(['part' => 'A', 'quote' => 1]); // null > > If ['quote' => null] matched a missing quote, the first two calls would become the > same pattern and the stored shape would be wrong. > > The same parser requires a real int for a score-like field, in 0..100 inclusive. is_int() is > the type check; the range is applied only after that. These all fail: > > ['strength' => '80'] > ['strength' => 80.0] > ['strength' => 101] > ['relevant' => 1] // is_bool(), same rule: no coercion > ['relevant' => 'true'] > > and ['strength' => 80] with ['relevant' => true] passes. An int > pattern therefore has to reject a numeric string and a float. A range pattern such as >=0 & > <=100 has to do the same when it is standing in for that field; "80" and 80.0 are > inside the numeric range and are still the wrong type. > > I am not asking for a change to the feature set. The written array patterns already say > array_key_exists(), and an int pattern that follows is_int() is what this code can adopt. > > Kevin Lopez

« previous php.internals (#132899) next »