Ruby瘾君子在字符串中寻找PHP子表达式 上下文 PHP5.3.x 概述

Ruby瘾君子在字符串中寻找PHP子表达式 上下文 PHP5.3.x 概述,php,ruby,comparison,string-interpolation,Php,Ruby,Comparison,String Interpolation,在与一位经常使用php和ruby的同事进行代码审查后,与ruby相比,php中的字符串插值遇到了一个有趣的挑战 问题: 假设颜色为“橙色” Ruby: puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now."); print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now."); PHP: puts(

在与一位经常使用php和ruby的同事进行代码审查后,与ruby相比,php中的字符串插值遇到了一个有趣的挑战

问题: 假设颜色为“橙色”

Ruby:

puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now.");
print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now.");
PHP:

puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now.");
print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now.");
挑战:有人能指定一种方法让PHP版本表现得像Ruby吗

警告
这个挑战旨在作为一个有趣的练习,限制只使用纯PHP。这并不适用于严肃的PHP项目。对于严重的PHP项目,开发人员将要考虑ADDN库,例如. 很接近,您可以在字符串中嵌入变量,但不能在函数调用中嵌入变量

为此,我使用了
printf()
(和
sprintf()
),这是一个围绕同名C函数的薄包装:

printf('My favorite color is %sish -- at least for now.', strtolower( $color ));
看到那里的
%s
了吗?这是作为第二个参数传入的字符串数据类型的占位符

sprintf()
的工作方式相同,但它返回格式化字符串,而不是打印

唯一的其他选择是:

A.首先执行函数调用,并将最终结果分配给变量:

$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");
B.使用串联,这在我看来有点难看:

print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');
您可能已经注意到我使用单引号(也称为勾号)和双引号

在PHP中,双引号内的文本被解析为变量,如上面的“A”所示

不分析单引号内的文字。正因为如此,它们速度更快。通常,只有在需要解析变量时,才应该在文本周围使用双引号

'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

我认为PHP不支持插入字符串的完整表达式。但是我已经有一段时间没有使用PHP了。

不可能。但是如果你真的坚持,你总是可以创建一个具有流畅接口的String类。。。但这太疯狂了:)

你不能像那样在字符串中调用普通函数,但你可以诱使解析器做一些奇怪的事情:

<?php
print "{$a->b()}"; // Works

//Parse error: syntax error, unexpected '(' in Command line code on line 1
print "${time()}";

print "${$a=time()} $a"; // Also works: prints "1234380996"
?>

只要它在开始时看到一个有效的变量,它就会毫无怨言地插入整个语句

对于那些想知道的人来说,是的,这也有效

<?php
print "${$a or print shell_exec('ls')}";
?>

如果有什么事情发生

class ColorIsh {
    var $color;

    function __constructor($color) { $this->color = $color; }
    function __get($prop) {
        if ($prop == 'ish') {
            // code here fixing suffix if needed
            return strtolower($this->color) . 'ish';
        }
        return '';
    }
    function __set($prop) {}
}

$color = new ColorIsh("orange");
$str = "My favorite color is $color->ish -- at least for now.";
还有超高级版本

class ColorIsh {
    private $color;

    function __constructor($color) {$this->color = $color; }
    function __get($prop) {
        if ($prop == 'color') 
            return $this->color;
        if ($prop == 'ish')
            return isset($this->ish) ? $this->ish : $this->color . 'ish';
        return false;
    }
    function __set($prop, $value) {
        if ($prop == 'color') { $this->color = $value; unset($this->ish); }
        if ($prop == 'ish') { $this->ish = $value; }
    }
}

$color = new ColorIsh('orange');
$color->ish = 'orangish';
print "The color is kinda $color->ish";
$color->color = 'green';
print "The color is kinda $color->ish";

output:
The color is kinda orangish.
The color is kinda greenish.

它不是很漂亮,但是你可以使用匿名函数

$e = function($val) { return $val; };
$foo = 'foo';
echo "Uppercase foo = {$e(strtoupper($foo))}";
我的项目通常有一个helper函数,它返回上面的匿名函数,因此不需要每次都重新创建它

function returner() {
    static $returner;

    if (!$returner) {
        $returner = function($val) {
            return $val;
        };
    }

    return $returner;
}

$e = returner();

在您的源代码中,它总是看起来更干净,所需的处理更少:$myVar='ValueBlah'。strtolower($myArg)。'我的绳子的末端';通过这种方式,您可以在使用源代码时看到整行突出显示的语法。尽管如此,我还是投了赞成票,因为这是一个很好的答案。@Syntax,我不同意“较少处理”的评论。字符串解析在v4.0和v5.0之间的效率有了很大的飞跃。我不确定你的观点,但Zend Studio for Eclipse在嵌入变量时会突出显示语法。@语法:这是一种看待它的方式。但是,对于那些希望执行myArg.tolowercase().reverse().stripspaces()而不必嵌套所有这些括号的人,会发生什么呢?您可以使用嵌套的括号,很简单。它是PHP,不是Ruby,它不是。双引号字符串是为变量而不是函数分析的。单引号字符串根本不被解析。这很可怕。很高兴我从不使用双引号。@Mario,其实没那么糟糕。PHP不会在变量中执行该代码,因此您不会因此而对代码注入敞开大门。试试上面的例子。但将其分配给一个变量:$x='$a->b();打印({$x});这只是要打印字面的PHP代码,并不像看上去那么糟糕。获得代码注入的唯一方法是,如果用户能够控制PHP代码本身中的硬编码字符串,那么此时您可能已经完蛋了。但是,能够调用这样的函数有点奇怪。好的,很好,呵呵。我开始回想我早期的PHP代码。+1!这就是为什么我喜欢PHP,你有时可以在代码中找到隐藏的宝藏……注意:你没有注意到我说这个答案是“在那里”吗?如果不清楚,我不建议任何人使用上述代码。我只是想说明ruby代码的“等价物”是“可能的”。