PHP 延迟字符串插值

4
有没有一种方法可以在后续的插值中“准备”一个字符串(而不使用自定义扩展函数)?例如:
class Test {
    private static $STR_VAL = "the val is $v";

    public static function printVal($v) {
        echo self::$STR_VAL;
    }
}

为什么需要将字符串提取到静态成员中? - Eric
1
@Eric 为什么不呢?将模板字符串与值分离,而不是在某个方法的任何地方内联编写每个文本,这并不罕见。 - KingCrunch
这只是一个简化的例子。想象一下,你需要在20个不同的地方使用这个字符串。 - mkvcvc
@cbaby:难道不是Test::printVal的工作来生成这个字符串吗?格式字符串应该只出现在一个地方——在printVal内部。所有其他引用都应该调用printVal - Eric
1
@Eric:那么,您总是需要搜索printVal()来更改模板吗?请记住,您可能有更多这样的模板,您也可以将它们放到完全分离/不同的类中,并且它们可能被多个方法使用。 - KingCrunch
显示剩余4条评论
2个回答

8

sprintf()

class Test {
    private static $STR_VAL = "the val is %s";

    public static function printVal($v) {
        echo sprintf(self::$STR_VAL, $v);
    }
}

“echo sprintf()”是一种“反模式”。绝对没有任何理由让任何人在任何代码中编写“echo sprintf()”,每次都应该使用“printf()”。 - mickmackusa
FYI:我的SEDE查询:SELECT a.Id as [帖子链接], a.CreationDate FROM Posts a INNER JOIN posts q ON q.id = a.parentid WHERE q.tags LIKE '%<##tag?php##>%' AND a.PostTypeId = 2 AND LEN(a.Body) < 300 AND a.Body LIKE '%echo sprintf(%' ORDER BY a.CreationDate ASC - mickmackusa
@mickmackusa 谁告诉你sprintf是反模式的?相反,我学到的是,printf是反模式,因为当输出什么时,你失去了控制。在非线性应用程序中——现在几乎每个应用程序都是非线性的——这可能会导致奇怪的问题,实际上没有人想要“到处输出!!111”。除此之外:sprintf和普通字符串插值有些相似,而sprintf在处理数据类型时更加强大。我真的很想知道你的观点来自哪里。另外:你的第二条评论似乎属于不同的帖子。 - KingCrunch
1
SEDE查询是我如何查找所有包含 echo sprintf() 的Stack Overflow答案。sprintf()不是反模式--我经常使用这个函数。真正的反模式是立即回显 sprintf() 的返回值。当需要这样做时,应该使用printf()。我们不应该在任何代码中看到echo sprintf(),无论出于什么原因。 - mickmackusa

0

如果您想保留实际变量插值的解决方案:

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'));
    }
}

虽然我在这段代码中没有看到任何明显的攻击,但需要注意的是,在处理不受信任的字符串时,使用eval()可能会成为注入代码的一个可能向量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接