Есть ли в 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]);