带有命名参数的vsprintf或sprintf,或PHP中的简单模板解析

Jer*_* S. 12 php string.format printf templates named-parameters

我正在寻找一种方法来为或使用命名参数.sprintfprintf

例:

sprintf(
  'Last time logged in was %hours hours, 
   %minutes minutes, %seconds seconds ago'
  ,$hours,$minutes, $seconds
);
Run Code Online (Sandbox Code Playgroud)

或通过vsprintf和一个关联数组.

我在这里找到了一些编码示例

function sprintfn ($format, array $args = array())
Run Code Online (Sandbox Code Playgroud)

http://php.net/manual/de/function.sprintf.php

和这里

function vnsprintf( $format, array $data)
Run Code Online (Sandbox Code Playgroud)

http://php.net/manual/de/function.vsprintf.php

人们写自己的解决方案.

但我的问题是,是否有可能有一个标准的PHP解决方案来实现这一点,还是有另一种方式,也许是由PEAR提供的简单的PHP模板,我可以通过坚持标准的PHP实现这一点?

谢谢你的帮助.

Ale*_*orb 22

迟到了,但您可以简单地使用strtr来“翻译字符或替换子字符串”

<?php

$hours = 2;
$minutes = 24;
$seconds = 35;

echo strtr(
    'Last time logged in was %hours hours, %minutes minutes, %seconds seconds ago',
    [
        '%hours' => $hours,
        '%minutes' => $minutes,
        '%seconds' => $seconds
    ]
);
Run Code Online (Sandbox Code Playgroud)

输出以下内容:

上次登录是 2 小时 24 分 35 秒前

  • 强烈投票给strtr!我讨厌 sprintf,翻译者很少理解占位符,尤其是当有多个占位符时。“Shipped %1$d on %2$s”没有传达任何信息,并且很容易出现输入错误,而“Shipped [QUANTITY] on [DATE]”(或类似内容)对每个人来说都很清楚。 (3认同)
  • 这应该是公认的答案。炸药!尽管我更喜欢使用“{replace_me}”而不是“%replace_me”。 (2认同)

Nic*_*ini 16

我已经为这个需求编写了一个小组件.它叫做StringTemplate.有了它,你可以用这样的代码得到你想要的东西:

$engine = new StringTemplate\Engine;

$engine->render(
   'Last time logged in was {hours} hours, {minutes} minutes, {seconds} seconds ago',
   [
      'hours' => '08',
      'minutes' => 23,
      'seconds' => 12,
   ]
);
//Prints "Last time logged in was 08 hours, 23 minutes, 12 seconds ago"
Run Code Online (Sandbox Code Playgroud)

希望能有所帮助.

  • 这不是和```strtr()```一样吗? (2认同)
  • @JoLoCo 对于平面数组,是的,它与“strtr”相当。但 StringTemplate 也支持嵌套数组,如[此测试用例](https://github.com/nicmart/StringTemplate/blob/master/tests/StringTemplate/EngineTest.php)所示。 (2认同)

Kam*_*šík 12

据我所知,printf/sprintf不接受关联数组.

但是有可能做到 printf('%1$d %1$d', 1);

有总比没有好 ;)

  • str_replace / preg_replace / strtr-但我怀疑这就是您要寻找的。您还可以利用HEREDOC语法(http://php.net/heredoc) (2认同)

Rob*_*mer 5

这是来自php.net

function vnsprintf( $format, array $data)
{
    preg_match_all( '/ (?<!%) % ( (?: [[:alpha:]_-][[:alnum:]_-]* | ([-+])? [0-9]+ (?(2) (?:\.[0-9]+)? | \.[0-9]+ ) ) ) \$ [-+]? \'? .? -? [0-9]* (\.[0-9]+)? \w/x', $format, $match, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
    $offset = 0;
    $keys = array_keys($data);
    foreach( $match as &$value )
    {
        if ( ( $key = array_search( $value[1][0], $keys, TRUE) ) !== FALSE || ( is_numeric( $value[1][0] ) && ( $key = array_search( (int)$value[1][0], $keys, TRUE) ) !== FALSE) )
        {
            $len = strlen( $value[1][0]);
            $format = substr_replace( $format, 1 + $key, $offset + $value[1][1], $len);
            $offset -= $len - strlen( 1 + $key);
        }
    }
    return vsprintf( $format, $data);
}
Run Code Online (Sandbox Code Playgroud)

例:

$example = array(
    0 => 'first',
    'second' => 'second',
    'third',
    4.2 => 'fourth',
    'fifth',
    -6.7 => 'sixth',
    'seventh',
    'eighth',
    '9' => 'ninth',
    'tenth' => 'tenth',
    '-11.3' => 'eleventh',
    'twelfth'
);

echo vnsprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s %12$s<br />', $example); // acts like vsprintf
echo vnsprintf( '%+0$s %second$s %+1$s %+4$s %+5$s %-6.5$s %+6$s %+7$s %+9$s %tenth$s %-11.3$s %+10$s<br />', $example);
Run Code Online (Sandbox Code Playgroud)

例2:

$examples = array(
    2.8=>'positiveFloat',    // key = 2 , 1st value
    -3=>'negativeInteger',    // key = -3 , 2nd value
    'my_name'=>'someString'    // key = my_name , 3rd value
);

echo vsprintf( "%%my_name\$s = '%my_name\$s'\n", $examples);    // [unsupported]
echo vnsprintf( "%%my_name\$s = '%my_name\$s'\n", $examples);    // output : "someString"

echo vsprintf( "%%2.5\$s = '%2.5\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%2.5\$s = '%2.5\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%+2.5\$s = '%+2.5\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%+2.5\$s = '%+2.5\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%-3.2\$s = '%-3.2\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%-3.2\$s = '%-3.2\$s'\n", $examples);        // output : "negativeInteger"

echo vsprintf( "%%2\$s = '%2\$s'\n", $examples);            // output : "negativeInteger"
echo vnsprintf( "%%2\$s = '%2\$s'\n", $examples);            // output : [= vsprintf]

echo vsprintf( "%%+2\$s = '%+2\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%+2\$s = '%+2\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%-3\$s = '%-3\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%-3\$s = '%-3\$s'\n", $examples);        // output : "negativeInteger"
Run Code Online (Sandbox Code Playgroud)


Arm*_*tes 5

我知道这已经解决了太久了,但也许我的解决方案很简单,但对其他人有用.

使用这个小功能,您可以模仿简单的模板系统:

function parse_html($html, $args) {

  foreach($args as $key => $val) $html = str_replace("#[$key]", $val, $html);

  return $html;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

$html = '<h1>Hello, #[name]</h1>';
$args = array('name' => 'John Appleseed';

echo parse_html($html,$args);
Run Code Online (Sandbox Code Playgroud)

这将输出:

<h1>Hello, John Appleseed</h1>
Run Code Online (Sandbox Code Playgroud)

也许不适合每个人和每个案例,但它救了我.