A solution if you want to preserve actual variable interpolation:
function interpolate_string($string, $vars) {
extract($vars);
return eval('return "' . addslashes($string) . '";');
}
class Test {
//Note the single quote to prevent interpolation here
private static $STR_VAL = 'the val is $v';
public static function printVal($v) {
echo interpolate_string(self::$STR_VAL, compact('v'));
}
}
While I don't see any obvious attacks in this particular code, it should be noted that the use of eval() is a possible vector for code injection when dealing with untrusted strings.
Test::printValto generate this string? The format string should appear in only one place - insideprintVal. All other references should callprintVal.printVal()to make changes to the template? Remember, that you may have much more such templates, that you may also place into a completely separate/different classes and they may be used by more than a single method.