Ruby 爱好者在字符串中寻找 PHP 子表达式

发布于 2024-07-13 08:28:11 字数 688 浏览 13 评论 0原文

上下文

  • PHP 5.3.x

概述

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

问题

假设 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.");

挑战:任何人都可以指定一种方法,使 PHP 版本的行为像 Ruby 一样吗?

警告

此挑战旨在作为一项有趣的练习,但仅限于使用直接 PHP。 这不适用于严肃的 PHP 项目。 对于严肃的 PHP 项目,开发人员需要考虑插件库,例如 TWIG

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.

Question

Assume 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?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

云淡风轻 2024-07-20 08:28:11

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

为此,我使用 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”中所示。

单引号内的文字不会被解析。 正因为如此,它们速度更快。 通常,当需要解析变量时,您应该仅在文字周围使用双引号。

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('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.

sprintf() works the same way, but it returns the formatted string instead of print'ing it.

The only other options are:

A. Performing the function calls first and assigning the end-result to the variable:

$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");

B. Using concatenation, which is a little ugly 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.

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.

謸气贵蔟 2024-07-20 08:28:11
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

我认为 PHP 不支持插入字符串的完整表达式。 虽然我已经有一段时间没有接触过 PHP 了。

'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.

爱的那么颓废 2024-07-20 08:28:11

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

<?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')}";
?>

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')}";
?>
东走西顾 2024-07-20 08:28:11

如果这是什么事的话......

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.

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.
眼藏柔 2024-07-20 08:28:11

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

$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();

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();
雨夜星沙 2024-07-20 08:28:11

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

Not possible. But if you really insist, you can always create a String class with a fluent interface... but that's crazy :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文