> 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
