22

またはに名前付き引数を使用する方法を探しています。sprintfprintf

例:

sprintf(
  'Last time logged in was %hours hours, 
   %minutes minutes, %seconds seconds ago'
  ,$hours,$minutes, $seconds
);

vsprintfまたは、連想配列を介して。

ここでいくつかのコーディング例を見つけました

function sprintfn ($format, array $args = array())

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

そしてここ

function vnsprintf( $format, array $data)

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

人々が独自の解決策を書いた場所。

しかし、私の質問は、これを達成するための標準的な PHP ソリューションがあるのでしょうか、それとも、標準の PHP に固執することでこれを達成できる、PEAR が提供する単純な PHP テンプレートを使用する別の方法があるのでしょうか?

助けてくれてありがとう。

4

10 に答える 10

22

このニーズにぴったりの小さなコンポーネントを作成しました。これは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"

それが役立つことを願っています。

于 2013-08-14T15:33:17.247 に答える
15

私の知る限り、printf/sprintf は連想配列を受け入れません。

しかし、それは可能ですprintf('%1$d %1$d', 1);

何もないよりマシ ;)

于 2011-04-18T11:27:49.327 に答える
6

これは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);
}

例:

$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);

例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"
于 2012-01-03T04:04:07.603 に答える
5

これは長い間解決されてきましたが、おそらく私の解決策は十分に単純ですが、他の誰かにとっては便利です.

この小さな関数を使用すると、単純なテンプレート システムを模倣できます。

function parse_html($html, $args) {

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

  return $html;
}

次のように使用します。

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

echo parse_html($html,$args);

これは次のように出力されます。

<h1>Hello, John Appleseed</h1>

万人向けではないかもしれませんが、私は救われました。

于 2014-06-15T04:04:40.487 に答える
4

drupal の実装を見る

https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/format_string/7

シンプルで、正規表現を使用しません

function format_string($string, array $args = array()) {
  // Transform arguments before inserting them.
  foreach ($args as $key => $value) {
    switch ($key[0]) {
      case '@':
        // Escaped only.
        $args[$key] = check_plain($value);
        break;

      case '%':
      default:
        // Escaped and placeholder.
        $args[$key] = drupal_placeholder($value);
        break;

      case '!':
        // Pass-through.
    }
  }
  return strtr($string, $args);
}

function drupal_placeholder($text) {
  return '<em class="placeholder">' . check_plain($text) . '</em>';
}

例:

$unformatted = 'Hello, @name';
$formatted = format_string($unformatted, array('@name' => 'John'));
于 2015-12-20T16:34:42.677 に答える
2

これは本当に最善の方法です。不可解な文字は使用せず、キー名を使用するだけです!

PHP サイトからの抜粋: http://www.php.net/manual/en/function.vsprintf.php

function dsprintf() {
  $data = func_get_args(); // get all the arguments
  $string = array_shift($data); // the string is the first one
  if (is_array(func_get_arg(1))) { // if the second one is an array, use that
    $data = func_get_arg(1);
  }
  $used_keys = array();
  // get the matches, and feed them to our function
  $string = preg_replace('/\%\((.*?)\)(.)/e',
    'dsprintfMatch(\'$1\',\'$2\',\$data,$used_keys)',$string);
  $data = array_diff_key($data,$used_keys); // diff the data with the used_keys
  return vsprintf($string,$data); // yeah!
}

function dsprintfMatch($m1,$m2,&$data,&$used_keys) {
  if (isset($data[$m1])) { // if the key is there
    $str = $data[$m1];
    $used_keys[$m1] = $m1; // dont unset it, it can be used multiple times
    return sprintf("%".$m2,$str); // sprintf the string, so %s, or %d works like it should
  } else {
    return "%".$m2; // else, return a regular %s, or %d or whatever is used
  }
}

$str = <<<HITHERE
Hello, %(firstName)s, I know your favorite PDA is the %(pda)s. You must have bought %(amount)s
HITHERE;

$dataArray = array(
  'pda'         => 'Newton 2100',
  'firstName'   => 'Steve',
  'amount'      => '200'
);
echo dsprintf($str, $dataArray);
// Hello, Steve, I know your favorite PDA is the Newton 2100. You must have bought 200
于 2013-02-07T18:24:14.767 に答える