Ruby наркоман ищет PHP-подвыражения в строках - PullRequest
2 голосов
/ 11 февраля 2009

Контекст

  • PHP 5.3.x

Обзор

После проверки кода сотрудником, который регулярно использует и php, и ruby, возникла забавная проблема с интерполяцией строк в php по сравнению с ruby.

Вопрос

Предположим, цвет = "оранжевый";

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 .

Ответы [ 6 ]

8 голосов
/ 11 февраля 2009

Вы близки, вы можете вставлять переменные в строки, но не вызовы функций.

Я использую 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» выше.

Литералы внутри одинарных кавычек не анализируются. Из-за этого они быстрее. Вы должны, как правило, использовать двойные кавычки только вокруг литералов, когда есть переменная для анализа.

4 голосов
/ 11 февраля 2009
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

Я не думаю, что PHP поддерживает полные выражения, интерполированные в строки. Хотя прошло некоторое время с тех пор, как я сделал какой-нибудь PHP.

2 голосов
/ 03 июня 2016

Это не так красиво, но вы можете использовать анонимную функцию.

$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();
2 голосов
/ 11 февраля 2009

Если это что-то идет ....

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.
2 голосов
/ 11 февраля 2009

Вы не можете вызывать обычные функции внутри таких строк, но вы можете заставить парсер делать странные вещи:

<?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')}";
?>
1 голос
/ 11 февраля 2009

Не возможно. Но если вы действительно настаиваете, вы всегда можете создать класс String с беглым интерфейсом ... но это безумие:)

...