Ruby上瘾者寻找字符串中的PHP子表达
-
22-08-2019 - |
题
语境
- PHP 5.3.x
概述
与Ruby相比,与同时使用PHP和Ruby同时使用PHP和Ruby的同事进行代码审查后,在PHP中的字符串插值中出现了一个有趣的挑战。
问题
假设颜色=“橙色”;
红宝石:
puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now.");
PHP:
print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now.");
挑战: 任何人都可以指定一种使PHP版本像Ruby一样行为的方法吗?
警告
这项挑战旨在作为有趣的练习,其限制仅使用直PHP。这不是针对认真的PHP项目。对于认真的PHP项目,开发人员将需要考虑插件库,例如 枝条.
解决方案
您不能在类似的字符串中调用普通功能,但是您可以哄骗解析器做奇怪的事情:
<?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')}";
?>
其他提示
您很接近,您可以将变量嵌入字符串中,而不是函数调用。
我用 printf()
(和 sprintf()
),这是围绕同名C函数的薄包装器:
printf('My favorite color is %sish -- at least for now.', strtolower( $color ));
看到 %s
在那里?这是您作为第二参数传递的字符串数据类型的占位符。
sprintf()
以相同的方式工作,但它返回格式化的字符串而不是打印。
唯一的其他选项是:
答:首先执行函数调用并将最终归值分配给变量:
$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");
B.使用串联,这有点丑陋的IMO:
print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');
您可能已经注意到我对单引号(又名tick)和双引号的使用。
在PHP中,您在上面的“ A”中看到的变量中,双引号内的文字被解析。
单引号中的文字没有解析。因此,它们更快。通常,您应该只在有一个要解析的变量时才使用围绕文字的双重报价。
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'
我认为PHP不支持将完整的表达方式插入字符串中。自从我做任何PHP以来已经有一段时间了。
如果这是什么...
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))}";
我的项目通常具有辅助功能,该功能返回上述匿名功能,因此每次都不需要重新创建它。
function returner() {
static $returner;
if (!$returner) {
$returner = function($val) {
return $val;
};
}
return $returner;
}
$e = returner();
不可能。但是,如果您真的坚持认为,您总是可以创建一个带有流利界面的字符串类...但是这太疯狂了:)