Context
- PHP 5.3.x
Overview
After doing a code-review with an associate who uses both php and ruby routinely, a fun challenge came up on string interpolation in php compared to ruby.
在与常规使用php和ruby的同事进行代码审查之后,与ruby相比,php中的字符串插值有了一个有趣的挑战。
Question
Assume color = "orange";
假设color =“orange”;
Ruby:
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.");
Challenge: can anyone specify a way to get the PHP version behave like Ruby?
挑战:任何人都可以指定一种方法来使PHP版本像Ruby一样吗?
Caveat
This challenge is intended as a fun exercise with the constraint of using only straight PHP. This is not intended for serious PHP projects. For serious PHP projects, the developer will want to consider addon libraries, such as TWIG.
这个挑战旨在作为一种有趣的练习,仅限于使用直接PHP。这不适用于严肃的PHP项目。对于严肃的PHP项目,开发人员需要考虑插件库,例如TWIG。
6 个解决方案
#1
You can't call plain functions inside strings like that, but you can coax the parser into doing strange things:
你不能在这样的字符串中调用普通函数,但是你可以让解析器做一些奇怪的事情:
<?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"
?>
As long as it sees a valid variable at the start, it'll go ahead and interpolate an entire statement without complaining.
只要它在开始时看到一个有效变量,它就会继续并插入整个语句而不会抱怨。
For those who were wondering, yes, this works too...
对于那些想知道的人,是的,这也有效...
<?php
print "${$a or print shell_exec('ls')}";
?>
#2
You're close, you can embed variables in strings, but not function calls.
你很接近,你可以在字符串中嵌入变量,但不能在函数调用中嵌入变量。
I use printf()
(and sprintf()
) for that, which is a thin wrapper around the C function of the same name:
我使用printf()(和sprintf()),这是一个围绕同名C函数的薄包装:
printf('My favorite color is %sish -- at least for now.', strtolower( $color ));
See that %s
in there? That's the placeholder for the string data type that you're passing in as the 2nd argument.
看到%s在那里?这是您作为第二个参数传入的字符串数据类型的占位符。
sprintf()
works the same way, but it returns the formatted string instead of print'ing it.
sprintf()以相同的方式工作,但它返回格式化的字符串而不是打印它。
The only other options are:
唯一的其他选择是:
A. Performing the function calls first and assigning the end-result to the variable:
A.首先执行函数调用并将最终结果赋给变量:
$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");
B. Using concatenation, which is a little ugly IMO:
B.使用串联,这是一个有点丑陋的IMO:
print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');
You may have noticed my use of single quotes (aka ticks), and double quotes.
您可能已经注意到我使用单引号(也称为刻度)和双引号。
In PHP, literals inside double quotes are parsed for variables, as you see in "A" above.
在PHP中,双引号内的文字被解析为变量,如上面的“A”所示。
Literals inside single quotes are not parsed. Because of this, they're faster. You should, as a rule, only use double-quotes around literals when there's a variable to be parsed.
单引号内的文字不会被解析。因此,它们更快。作为一项规则,当有一个要解析的变量时,你应该只在文字周围使用双引号。
#3
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'
I dont think PHP supports full expressions interpolated into strings. Been a while since I did any PHP though.
我不认为PHP支持插入字符串的完整表达式。从我做过任何PHP以来已经有一段时间了。
#4
If this is anything goes....
如果这是任何事情......
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.";
And the hyper advanced version
和超高级版本
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.
#5
It's not that pretty, but you can use an anonymous function.
它不是很漂亮,但你可以使用匿名函数。
$e = function($val) { return $val; };
$foo = 'foo';
echo "Uppercase foo = {$e(strtoupper($foo))}";
My projects usually have a helper function which returns the above anonymous function, so it doesn't need to be recreated every time.
我的项目通常有一个辅助函数,它返回上面的匿名函数,因此不需要每次都重新创建它。
function returner() {
static $returner;
if (!$returner) {
$returner = function($val) {
return $val;
};
}
return $returner;
}
$e = returner();
#6
Not possible. But if you really insist, you can always create a String class with a fluent interface... but that's crazy :)
不可能。但是如果你真的坚持,你总是可以创建一个具有流畅界面的String类......但这太疯狂了:)
#1
You can't call plain functions inside strings like that, but you can coax the parser into doing strange things:
你不能在这样的字符串中调用普通函数,但是你可以让解析器做一些奇怪的事情:
<?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"
?>
As long as it sees a valid variable at the start, it'll go ahead and interpolate an entire statement without complaining.
只要它在开始时看到一个有效变量,它就会继续并插入整个语句而不会抱怨。
For those who were wondering, yes, this works too...
对于那些想知道的人,是的,这也有效...
<?php
print "${$a or print shell_exec('ls')}";
?>
#2
You're close, you can embed variables in strings, but not function calls.
你很接近,你可以在字符串中嵌入变量,但不能在函数调用中嵌入变量。
I use printf()
(and sprintf()
) for that, which is a thin wrapper around the C function of the same name:
我使用printf()(和sprintf()),这是一个围绕同名C函数的薄包装:
printf('My favorite color is %sish -- at least for now.', strtolower( $color ));
See that %s
in there? That's the placeholder for the string data type that you're passing in as the 2nd argument.
看到%s在那里?这是您作为第二个参数传入的字符串数据类型的占位符。
sprintf()
works the same way, but it returns the formatted string instead of print'ing it.
sprintf()以相同的方式工作,但它返回格式化的字符串而不是打印它。
The only other options are:
唯一的其他选择是:
A. Performing the function calls first and assigning the end-result to the variable:
A.首先执行函数调用并将最终结果赋给变量:
$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");
B. Using concatenation, which is a little ugly IMO:
B.使用串联,这是一个有点丑陋的IMO:
print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');
You may have noticed my use of single quotes (aka ticks), and double quotes.
您可能已经注意到我使用单引号(也称为刻度)和双引号。
In PHP, literals inside double quotes are parsed for variables, as you see in "A" above.
在PHP中,双引号内的文字被解析为变量,如上面的“A”所示。
Literals inside single quotes are not parsed. Because of this, they're faster. You should, as a rule, only use double-quotes around literals when there's a variable to be parsed.
单引号内的文字不会被解析。因此,它们更快。作为一项规则,当有一个要解析的变量时,你应该只在文字周围使用双引号。
#3
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'
I dont think PHP supports full expressions interpolated into strings. Been a while since I did any PHP though.
我不认为PHP支持插入字符串的完整表达式。从我做过任何PHP以来已经有一段时间了。
#4
If this is anything goes....
如果这是任何事情......
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.";
And the hyper advanced version
和超高级版本
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.
#5
It's not that pretty, but you can use an anonymous function.
它不是很漂亮,但你可以使用匿名函数。
$e = function($val) { return $val; };
$foo = 'foo';
echo "Uppercase foo = {$e(strtoupper($foo))}";
My projects usually have a helper function which returns the above anonymous function, so it doesn't need to be recreated every time.
我的项目通常有一个辅助函数,它返回上面的匿名函数,因此不需要每次都重新创建它。
function returner() {
static $returner;
if (!$returner) {
$returner = function($val) {
return $val;
};
}
return $returner;
}
$e = returner();
#6
Not possible. But if you really insist, you can always create a String class with a fluent interface... but that's crazy :)
不可能。但是如果你真的坚持,你总是可以创建一个具有流畅界面的String类......但这太疯狂了:)