Есть ли в PHP функция, такая как строки шаблонов Python?

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

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'

Я знаю, что PHP позволяет писать:

"Hello $person"

и имеют $person подставили, но шаблоны можно повторно использовать в различных разделах кода?

8 ответов

Решение

Вы также можете использовать strtr:

$template = '$who likes $what';

$vars = array(
  '$who' => 'tim',
  '$what' => 'kung pao',
);

echo strtr($template, $vars);

Выходы:

tim likes kung pao

You can use template strings like

echo " Hello {$name} {$info["last_name"]}" where $name and $info array is previously defined.

Я думаю, что есть множество способов сделать это... но это приходит на ум.

$search = array('%who%', '%what_id%');
$replace = array('tim', 'kung pao');
$conference_target = str_replace(
    $search,
    $replace,
    "%who% likes %what%"
);

Ха, у нас даже был один в нашей среде, использующий vsprintf:

class Helper_StringFormat {

    public static function sprintf($format, array $args = array()) {

        $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

        for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
            $arg_pos = $match[0][2];
            $arg_len = strlen($match[0][0]);
            $arg_key = $match[1][0];

            if (! array_key_exists($arg_key, $arg_nums)) {
                user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
                return false;
            }
            $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
            $pos = $arg_pos + strlen($replace);
        }

        return vsprintf($format, array_values($args));
    }
}

Который выглядит так, как будто он со страницы sprintf

Это позволяет звонить как:

sprintfn('second: %(second)s ; first: %(first)s', array(
    'first' => '1st',
    'second'=> '2nd'
));

ОБНОВИТЬ
Вот обновление, чтобы делать то, что вы хотите... не полностью проверено, хотя

class Helper_StringFormat {

    public static function sprintf($format, array $args = array()) {
        $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

        for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_][\w\s]*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
            $arg_pos = $match[0][1];
            $arg_len = strlen($match[0][0]);
            $arg_key = $match[1][0];

            if (! array_key_exists($arg_key, $arg_nums)) {
                user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
                return false;
            }
            $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
            $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
        }

        return vsprintf($format, array_values($args));
    }
}

$str = "%(my var)s now work with a slight %(my var2)s";
$repl = array("my var" => "Spaces", "my var2" => "modification.");

echo Helper_StringFormat::sprintf($str, $repl);

ВЫХОД
Пробелы теперь работают с небольшой модификацией.

Другой более простой подход был бы следующим:

$s = function ($vars) {
    extract($vars);
    return "$who likes $what";
};
echo $s(['who' => 'Tim', 'what' => 'King Pao']); // Tim likes King Pao

И да, PHPStorm будет жаловаться...

Мне лично больше всего нравится sprintf (или vsprintf, для массива аргументов). Он размещает их в намеченном порядке, при необходимости приводит типы и имеет гораздо более продвинутые функции.

Пример:

      $var = sprintf("%s costs %.2f dollars", "Cookies", 1.1);

Это приведет к значению Cookies cost 1.10 dollars.

Существует целое семейство функций printf для различных случаев использования, все они перечислены в разделе «См. Также».

Очень универсален: одни и те же методы для предоставления переменных, компонентов массива, результатов функций и т. Д.

Я сделал функцию, чтобы делать то, что вы хотите. я сделал это "грязным и грязным", потому что у меня не так много времени на его рефакторизацию, может быть, я загружу его на свой github.

РЕДАКТИРОВАТЬ: исправление ошибки...

Используйте это как

    formattemplatter(
                     '$who likes $what'
                     , array(
                               'who'  => 'Tim'
                             , 'what' => 'Kung Pao'
                     )
    );

Переменные могут быть только [a-zA-Z0-9_].

 function formattemplater($string, $params) {
    // Determine largest string
    $largest = 0;
    foreach(array_keys($params) as $k) {
        if(($l=strlen($k)) > $largest) $largest=$l;
    }

    $buff   = '';

    $cp     = false;    // Conditional parenthesis
    $ip     = false;    // Inside parameter
    $isp    = false;    // Is set parameter

    $bl     = 1;    // buffer length
    $param  = '';   // current parameter

    $out    = '';  // output string
    $string .= '!';

    for($sc=0,$c=$oc='';isset($string{$sc});++$sc,++$bl) {
        $c = $string{$sc};

        if($ip) {
            $a = ord($c);

            if(!($a == 95 || (                  // underscore
                    ($a >= 48 && $a <= 57)      // 0-9
                    || ($a >= 65 && $a <= 90)   // A-Z
                    || ($a >= 97 && $a <= 122)  // a-z
                )
            )) {

                $isp = isset($params[$buff]);

                if(!$cp && !$isp) {
                    trigger_error(
                            sprintf(
                                    __FUNCTION__.': the parameter "%s" is not defined'
                                    , $buff
                            )
                            , E_USER_ERROR
                    );
                } elseif(!$cp || $isp) {
                    $out    .= $params[$buff];
                }

                $isp    = $isp && !empty($params[$buff]);
                $oc     = $buff = '';
                $bl     = 0;
                $ip     = false;
            }
        }

        if($cp && $c === ')') {
            $out .= $buff;

            $cp = $isp = false;
            $c  = $buff = '';
            $bl = 0;
        }

        if(($cp && $isp) || $ip)
            $buff .= $c;

        if($c === '$' && $oc !== '\\') {
            if($oc === '(')  $cp = true;
            else $out .= $oc;

            $ip   = true;
            $buff = $c = $oc = '';
            $bl   = 0;
        }

        if(!$cp && $bl > $largest) {
            $buff   = substr($buff, - $largest);
            $bl     = $largest;
        }

        if(!$ip && ( !$cp || ($cp && $isp))) {
            $out .= $oc;
            if(!$cp) $oc = $c;
        }
    }

    return $out;
}

Просто для полноты картины: есть еще Heredoc.

      $template = fn( $who, $what ) => <<<EOT
    $who likes $what
EOT;

echo( $template( 'tim', 'kung pao' ) );

Выходы:

      tim likes kung pao

Примечания:

  • Вы получаете подсветку на своем любимом языке (если правильно настроены). Просто замените EOT(из приведенного выше примера) тем, что вам нравится (ec HTML, SQL, PHP, ...).
  • Экранирование массивов фигурными скобками{$data['who']}. Доступ к таким объектам, как$data->whoработает без брекетов.
  • Стрелка работает какfn($a)=>$aдоступны начиная с PHP 7.4. Ты можешь написатьfunction($a){return $a;}если вы используете PHP<7.4.

Другой вариант — использовать

      <?php

echo msgfmt_format_message('en_GB', 'Tom has {0, plural, =0{no cat} =1{a cat} other{# cats}}', [0]), "\n";
echo msgfmt_format_message('en_GB', 'Tom has {0, plural, =0{no cat} =1{a cat} other{# cats}}', [1]), "\n";
echo msgfmt_format_message('en_GB', 'Tom has {0, plural, =0{no cat} =1{a cat} other{# cats}}', [2]), "\n";

echo msgfmt_format_message('de', 'Tom hat {cat, plural, =0{keine Katze} =1{eine Katze} other{# Katzen}} und {dog} Hunde', ['cat'=>12345, 'dog'=>-5.23]), "\n";

echo MessageFormatter::formatMessage('de', 'Tom hat {cat, plural, =0{keine Katze} =1{eine Katze} other{# Katzen}} und {dog,number} Hunde', ['cat'=>12, 'dog'=>-5.23]), "\n";

$fmt = new MessageFormatter('de', 'Tom hat {cat, plural, =0{keine Katze} =1{eine Katze} other{# Katzen}} und {dog,number} Hunde');
echo $fmt->format(['cat'=>12, 'dog'=>-5.23]);
Другие вопросы по тегам