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.