PHP 有没有像 Python 的模板字符串这样的特性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7683133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does PHP have a feature like Python's template strings?
提问by Casebash
Python has a feature called template strings.
Python 有一个称为模板字符串的特性。
>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
I know that PHP allows you to write:
我知道 PHP 允许你写:
"Hello $person"
and have $person
substituted, but the templates can be reused in various sections of the code?
并已$person
替换,但模板可以在代码的各个部分重复使用?
回答by James Coyle
回答by Miguel
You can use template strings like
您可以使用模板字符串,如
echo " Hello {$name} {$info["last_name"]}" where $name and $info array is previously defined.
echo " Hello {$name} {$info["last_name"]}" 其中 $name 和 $info 数组是先前定义的。
回答by sberry
I think there are a bunch of ways to do this... but this comes to mind.
我认为有很多方法可以做到这一点……但我想到了这一点。
$search = array('%who%', '%what_id%');
$replace = array('tim', 'kung pao');
$conference_target = str_replace(
$search,
$replace,
"%who% likes %what%"
);
Ha, we even had one in our framework using vsprintf:
哈,我们甚至在我们的框架中使用了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));
}
}
Which looks like it came from the sprintf page
看起来它来自sprintf 页面
This allows for calls like:
这允许调用如下:
sprintfn('second: %(second)s ; first: %(first)s', array(
'first' => '1st',
'second'=> '2nd'
));
UPDATE
Here is an update to do what you want... not fully tested though
更新
这是一个更新,可以做你想做的事……虽然没有经过全面测试
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);
OUTPUT
Spaces now work with a slight modification.
输出
空间现在只需稍作修改即可工作。
回答by Ron
Another more simple approach would be this:
另一种更简单的方法是:
$s = function ($vars) {
extract($vars);
return "$who likes $what";
};
echo $s(['who' => 'Tim', 'what' => 'King Pao']); // Tim likes King Pao
And yes, PHPStorm will complain...
是的,PHPStorm 会抱怨...
回答by Felipe Buccioni
I made a function to do what you want. i made it "quck-and-dirty" because i have not much time to refactorize it, maybe i upload it to my github.
我做了一个函数来做你想做的事。我把它弄得“又臭又臭”,因为我没有太多时间重构它,也许我将它上传到我的 github。
EDIT: a bug correction...
编辑:错误更正...
Use it like
使用它就像
formattemplatter(
'$who likes $what'
, array(
'who' => 'Tim'
, 'what' => 'Kung Pao'
)
);
Variables can be [a-zA-Z0-9_] only.
变量只能是 [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;
}