2

语境

  • PHP 5.3.x

概述

在与经常使用 php 和 ruby​​ 的同事进行代码审查后,与 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 项目,开发人员将需要考虑插件库,例如TWIG

4

6 回答 6

8

你很接近,你可以在字符串中嵌入变量,但不能在函数调用中。

为此,我使用printf()(and 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.使用连接,这有点难看IMO:

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

您可能已经注意到我使用单引号(也称为刻度)和双引号。

在 PHP 中,双引号内的文字被解析为变量,正如您在上面的“A”中看到的那样。

不解析单引号内的文字。因此,它们更快。作为一项规则,您应该只在有要解析的变量时在文字周围使用双引号。

于 2009-02-11T19:27:03.943 回答
4
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

我不认为 PHP 支持插入字符串的完整表达式。自从我做任何 PHP 以来已经有一段时间了。

于 2009-02-11T19:29:23.017 回答
2

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

<?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')}";
?>
于 2009-02-11T19:48:23.267 回答
2

如果这是任何事情......

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.
于 2009-02-11T19:53:30.697 回答
2

它不是那么漂亮,但您可以使用匿名函数。

$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();
于 2016-06-03T15:28:12.287 回答
1

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

于 2009-02-11T19:47:00.133 回答