かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP 文字列中に変数で値を埋め込むやつのメモ

"Hello, xxxx!": "こんにちは、xxxxさん!" みたいな key-value で翻訳テキストを出せる機能を作っていて PHP で既定の文字列に変数を埋め込む方法を何パターンかやってみたのでメモ

sprintf ・ vsprintf

所謂文字列のフォーマットに使うメソッドを利用する方法
既定の文字列で可変な部分に %s を埋め込んでおいて出力時にこの関数を噛ませれば良い

sprintf は変換する値を可変長引数を取れるので置き換える箇所が複数あっても問題ない

<?php
$str = "Hello, %s!";
echo sprintf($str, 'Ichigo');
// => "Hello, Ichigo!"

$str = "Hello, %s!, Hi, %s.";
echo sprintf($str, 'Aoi', 'Ran');
// => "Hello, Aoi!, Hi, Ran."

vsprintf は変換する値が可変長引数ではなく配列で渡すだけ

<?php
$str = "Hello, %s!";
echo vsprintf($str, ['Akari']);
// => "Hello, Akari!"

$str = "Hello, %s!, Hi, %s and %s!!";
echo vsprintf($str, ['Otome', 'Sakura', 'Shion']);
// => "Hello, Otome!, Hi, Sakura and Shion!!"

シンプルに変換できるし、%02d などでフォーマットも可能。(単数形と複数形のフォーマットもできれば完璧なのだけど…)
一方デメリットとしては、置換したい箇所が複数ある場合に値の渡す順番を正しく合わせる必要がある点。変換箇所が多いとどの値がどこに入るのか見通しが悪い点。

strtr

Laravel の翻訳関数調べてた際に存在を知った文字の変換・部分置換を行うためのメソッド

第1引数に変換する文字列を渡し第2引数に ['from (変換する文字)' => 'to (置換する文字)'] の配列を渡す。第2引数に from、第3引数に to を渡す方法もあるが配列を渡す方が効率が良さそう

次の例は、引数を二つだけ指定して strtr() をコールしたときの挙動を示すものです。置換の優先度 ("h" よりもっと長いキーに一致しているので、この置換は行われていないこと)、 そして一度置換した文字列はもう置換の対象にならないことを確認しましょう。
cf. PHP: strtr - Manual

<?php
$trans = array("h" => "-", "hello" => "hi", "hi" => "hello");
echo strtr("hi all, I said hello", $trans);
// => hello all, I said hi

一度変換した文字列は再変換されないのも便利!

Laravel の国際化メソッドのように使える

<?php
$str = ":unit は :name1, :name2, :name3 からなるユニットです!";
echo strtr($str, [
  ":unit" => "Soleil",
  ":name1" => "星宮いちご",
  ":name2" => "霧矢あおい",
  ":name3" => "紫吹蘭",
]);
// => "Soleil は 星宮いちご, 霧矢あおい, 紫吹蘭 からなるユニットです!"

echo strtr($str, [
  ":unit" => "Tristar",
  ":name1" => "神崎美月",
  ":name2" => "藤堂ユリカ",
  ":name3" => "一ノ瀬かえで",
]);
// => "Tristar は 神崎美月, 藤堂ユリカ, 一ノ瀬かえで からなるユニットです!"

echo strtr($str, [
  ":unit" => "Luminas",
  ":name1" => "大空あかり",
  ":name2" => "氷上すみれ",
  ":name3" => "新条ひなき",
]);
// => "Luminas は 大空あかり, 氷上すみれ, 新条ひなき からなるユニットです!"

べんり!!! strtr は何を何に置換するのか分かりやすいのが良いな!と感じました。

まとめ

  • フォーマットも行いたいときは sprintf vsprintf を使う
  • 文字列中の置換をわかりやすく行いたいときは strtr を使う

のが良さそうかなと思いました!
おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]