On Fri, Nov 6, 2026, at 6:59 AM, Artem Ukrainskiy wrote:
> Hi internals,
>
> I'd like to open discussion on this RFC:
> https://wiki.php.net/rfc/prepared_literal_string_matching
>
> It proposes Str\Matcher and Str\Replacer for prepared literal substring
> search and replacement. Matcher provides presence checks, unique matched
> keywords, occurrence counts, and enumeration of all overlapping matches
> with byte offsets, using Str\MatchResult objects. Replacer performs
> non-overlapping replacements, choosing the earliest start and then the
> longest key, without rescanning inserted text.
>
> Both classes prepare an immutable dictionary during construction.
> Matching is byte-oriented, binary-safe, and case-sensitive. Objects can be
> reused within a request or in long-running applications.
>
> I've implemented the API and published reproducible benchmarks covering
> both prepared calls and one-shot use, including construction and destruction.
> Preparation can pay off even for a single call on some inputs. On others,
> existing PHP functions or PCRE remain faster, even than a prepared object.
>
> I propose including these classes in ext/standard in the Str namespace.
> The current implementation is in ext/strmatch. I'd welcome feedback on
> the API, integration, error types, and whether Matcher and Replacer
> should be considered together or separately.
>
> Implementation:
> https://github.com/php/php-src/pull/25122
>
> Benchmarks, methodology and raw data:
> https://github.com/ArtUkrainskiy/php-src-bench/tree/main/reports/multi-pattern-search
>
> -- 
> Best regards, 
> Artem Ukrainskiy

This looks interesting, and I'm not opposed to it.  It somewhat parallels the 
recently discussed Pcre class.

My main question is that this feels very niche.  Based on the benchmarks, if 
I'm reading them correctly, it sounds like 90% of uses would be better served 
with the existing APIs.  Does this make sense for stdlib then?  It would be 
helpful to include more practical examples of where I'd want to use this 
instead of str_contains(), rather than just a table of byte counts.  The "Where 
the API can help" section isn't sufficient as-is.

For example... would this pay off in a long-running process like FrankenPHP or 
Swoole, if the object is saved between requests?

Other issues:

- Matcher::matchAll() returns a list, but each of the items in it contains, I 
believe, a unique value.  Could it then return a keyed array for easier lookup? 
 (The example suggests I may be wrong, but if so, please spell this out 
explicitly.)

- The inout $count argument to Replacer::replace(): Eew.  Please explore a 
better way of handling that.  inout params in a language like PHP are the 
absolute last resort.

- I'm not clear if it says explicitly anywhere if there's behavioral 
differences from the existing functions.  If so it wasn't clear.  Would 
swapping Replacer in for strtr() require any subtle logic changes, or is it a 
drop-in syntax change?  That should be made explicit.

- "Reinitializing an already prepared object throws an Error, even if its 
dictionary is empty." - How would one reinitialize it?  Do you mean calling the 
constructor explicitly, which PHP allows even though it's never ever safe to do 
anyway? :-)  If so, please clarify that's what you mean.

- "two distinct objects compare unequal with ==, even if their dictionaries are 
identical. " - I disagree with this.  The whole point of == on objects is to 
ask "are these equivalent," and two Matchers with the same dictionary are 
equivalent.  Thus they should be ==.

- The RFC notes that these routines are byte-based only, which is fine, as 
that's what most of PHP is.  However, is there a use for a Unicode/Grapheme 
equivalent?  Even if future scope, it's worth mentioning.

- In "Design choices," you list how existing implementations in other languages 
differ.  Please also explain why you've chosen to not follow the same semantics 
as one of the existing tools, as that means someone moving from those languages 
to PHP is going to be easily confused by the edge cases.

- In "Where existing tools are preferable", there's a broken link in the 2nd 
paragraph.

- These are closely related enough that I think a single vote is fine.  There's 
no need to separate them.

--Larry Garfield

Reply via email to