Avoid Unnecessary Replacements Loops
ID |
php.avoid_unnecessary_replacements_loops |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Efficiency |
Language |
Php |
Tags |
efficiency, loop |
Description
Reports a string-replacement call (str_replace, str_ireplace, preg_replace,
preg_replace_callback) inside a loop when every argument is a constant expression. Such a
call returns the same value on every iteration and can be computed once before the loop.
Rationale
A replacement whose subject, search and replacement are all constants does not depend on the
loop in any way, yet it is recomputed on every pass — and preg_replace additionally compiles
its pattern each time. Hoisting the call out of the loop performs the work once and stores the
result in a local variable.
To keep the rule precise on a dynamically typed language, only calls whose arguments are all constant (no variable references) are flagged: these are unambiguously loop-invariant. A call whose subject or pattern reads a loop variable is left untouched, since its result legitimately changes per iteration.
<?php
foreach ($rows as $row) {
$prefix = str_replace('-', '_', '/static/path'); // FLAW — constant arguments, recomputed each pass
$out[] = $prefix . $row;
}
$prefix = str_replace('-', '_', '/static/path'); // OK — computed once before the loop
foreach ($rows as $row) {
$out[] = $prefix . str_replace('-', '_', $row); // OK — subject varies with the loop
}
Remediation
Move the constant replacement to a local variable computed once before the loop, then reference that variable inside the loop body.