Literal Pattern Passed To preg_replace

ID

php.str_replace_preferred_preg_replace

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Efficiency

Language

Php

Tags

best-practice, efficiency

Description

preg_replace() is called with a pattern that contains no regular-expression syntax, so the PCRE engine is compiled and run to do what a plain string replacement does directly.

str_replace() (or str_ireplace() when the pattern carries the i modifier) produces the same result several times faster, and tells the reader at a glance that nothing clever is happening.

Rationale

$text = preg_replace('/foo/', 'bar', $text);
$text = preg_replace('#section#', 'part', $text);
$text = preg_replace('/HELLO/i', 'hi', $text);

Every one of these compiles a pattern, allocates the match machinery and walks the subject with the regular-expression engine, for a substring swap. A reader also has to scan the pattern for metacharacters before concluding there are none.

Remediation

$text = str_replace('foo', 'bar', $text);
$text = str_replace('section', 'part', $text);
$text = str_ireplace('HELLO', 'hi', $text);

An escaped punctuation character in the pattern is still a literal, so preg_replace('/a\.b/', …) becomes str_replace('a.b', …) — drop the backslash the pattern needed and the string function does not.

The trigger is deliberately narrow, because the opposite advice is the common one. Nothing is reported unless all of the following hold:

  • the pattern is a literal whose delimiters strip cleanly;

  • every character in it is ordinary, or an escape of an ASCII punctuation character — a quantifier, anchor, character class, group or alternation keeps the call as it is;

  • the only modifier, if any, is i; every other modifier changes how the subject is matched;

  • the call has exactly the three arguments str_replace takes, with a single pattern and a single replacement — an array of patterns, a $limit argument and preg_filter are all left alone;

  • the replacement contains no $ or \, which preg_replace reads as group references and escapes while str_replace copies them through.

© 2026 Xygeni. All rights reserved