Ruby瘾君子在字符串中寻找PHP子表达式 上下文 PHP5.3.x 概述
在与一位经常使用php和ruby的同事进行代码审查后,与ruby相比,php中的字符串插值遇到了一个有趣的挑战 问题: 假设颜色为“橙色” Ruby: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(
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代码的“等价物”是“可能的”。