PHP RFC: array_match
- Version: 0.1
- Date: 2026-08-22
- Author: Sepehr Mahmoudi, sepehrphpr@gmail.com
- Status: Draft
- Target Version: PHP 8.7
- Implementation: In Progress (TBD)
Introduction
Searching for a specific substring within an array of strings is a very common operation in PHP applications. Currently, developers must rely on array_filter() combined with a closure containing strpos() or str_contains(). This approach, while functional, introduces significant overhead due to the execution of userland closures for every element in the array.
This RFC proposes the introduction of a new function, array_match(), which performs this operation natively in C. This provides a simpler, more readable syntax and significantly improves performance by avoiding userland function call overhead.
Proposal
Introduce a new standard library function array_match().
Function Signature
Parameters
- $array: The input array to be searched.
- $needle: The substring to search for within the array values.
- $ignore_case: If set to
true, the search will be case-insensitive (similar tostripos). Iffalse(default), the search is case-sensitive (similar tostrpos).
Note: The function preserves the original keys of the array in the returned result. Non-string values in the array are safely cast to strings during the evaluation, or can be skipped depending on the final internal implementation choice.
Use Cases
The primary use cases for array_match() revolve around developer experience (DX) and performance:
- Log Filtering: Quickly extracting relevant log messages containing a specific error code or keyword from a large array of log lines.
- File/Directory Searches: Filtering an array of filenames or paths by a specific extension or partial name (e.g., finding all “.php” files in a scanned directory array).
- Data Processing: Searching through user inputs, database text dumps, or API responses where data is represented as an array of strings.
- Performance Optimization: Replacing heavily iterated
array_filter+ closure combinations in performance-critical loops with a single, highly optimized native C function.
Examples
Example 1: Case-sensitive search
$files = [ 'doc1.txt', 'image.PNG', 'script.php', 'index.PHP', 'readme.md' ]; $result = array_match( $files, '.php' ); print_r($result); /* Output: Array ( [2] => script.php ) */
In this example, the function searches for the exact string .php. Since the $ignore_case parameter is false by default, it performs a case-sensitive search. It only matches script.php and ignores index.PHP.
Example 2: Case-insensitive search
$files = [ 'doc1.txt', 'image.PNG', 'script.php', 'index.PHP', 'readme.md' ]; $result = array_match( $files, '.php', true ); print_r($result); /* Output: Array ( [2] => script.php [3] => index.PHP ) */
By setting the $ignore_case parameter to true, the function performs a case-insensitive search. It successfully matches both .php and .PHP, returning both script.php and index.PHP while preserving their original array keys.
Polyfill / Userland Equivalent
To demonstrate the exact behavior and to show how developers achieve this currently (without closure overhead), here is the userland equivalent using a foreach loop.
This polyfill highlights why a native implementation is beneficial: it removes the need for developers to write boilerplate loops for such a trivial and common task.
function array_match_polyfill( array $array, string $needle, bool $ignore_case = false ): array { $result = []; foreach ($array as $key => $value) { // Cast to string to ensure safe searching $stringValue = (string) $value; if ($ignore_case) { if (stripos($stringValue, $needle) !== false) { $result[$key] = $value; } } else { if (strpos($stringValue, $needle) !== false) { $result[$key] = $value; } } } return $result; }