PHPで扱える小型軽量"文字列特化"テンプレートエンジン "StringBuilder"

# 結論

- 大きなオブジェクトも準備せずにサクッとテンプレート文字列を扱いたいならおすすめ
- バリデーションエラーメッセージやエラーログ用文字列の構築に好適

# 必要なもの

PHP 7.2.0以降のPHP + ext-mbstring + [fw3/strings](https://packagist.org/packages/fw3/strings)

# 導入方法

`composer require fw3/strings`としてインストールできます。

[Packagist](https://packagist.org/packages/fw3/strings)

# 簡単な使い方

次の例の様に、特に事前準備することなく扱う事が出来ます。

第一引数にテンプレート文字列、第二引数にテンプレート引数で使う変数を配列として与えます。
標準では配列のキーの前後に`{:`、`}`をつけたものを変数展開すべき対象として認識します。
例においては変数`{:value1}`に対して配列のキー`'value1'`の値を埋め込み表示しています。

```:php
use fw3\strings\builder\StringBuilder;

echo StringBuilder::factory()->build('{:value1}はあります。', [
    'value1'    => 'VALUE1',
]);
// VALUE1はあります。と表示されます。
```

# 複雑な使い方

## 複数の値のうちどれか一つでもあればよい場合

いずれかの値が変数として存在する場合に、見つかり次第展開することもできます。

次の例では、`value1`、`value2`のいずれかの値があれば表示する例です。
`value1`が見つからなったため、`value2`の値が表示されています。
期待する変数は`:`で区切ります。

```:php
use fw3\strings\builder\StringBuilder;

echo StringBuilder::factory()->build('{:value1:value2}はあります。', [
    'value2'	=> 'VALUE2',
]);
// VALUE2はあります。と表示されます。
```

## 値に対する修飾

SmartやTwigのように変数に対して修飾を行う事も出来ます。
変数と修飾子は`|`(パイプ)で区切ります。

```:php
use fw3\strings\builder\StringBuilder;

echo StringBuilder::factory()->build('現在の時刻は{:now|date('Y/m/d H:i:s')}です。', [
    'now'	=> strtotime('2020/01/01 00:00:00'),
]);
// 現在の時刻は2020/01/01 00:00:00です。と表示されます。
```

デバッグやエラーログの取り扱いに便利な文字列の出力も行えます。

```:php
use fw3\strings\builder\StringBuilder;

echo StringBuilder::factory()->build('値はそれぞれ{:bool|to_debug}、{:null|to_debug}、{:string|to_debug}、{:array|to_debug}、{:array2|to_debug(2)}です。', [
    'bool'		=> false,
    'null'		=> NULL,
    'string'	=> '',
    'array'		=> [[[]]],
    'array2'	=> [[[]]],
]);
// 値はそれぞれfalse、’’、NULL、Array、[0 => [0 => Array]]です。と表示されます。
```

# クラス自体の機能

## 設定

標準で使用する変数セットや変数部の指定文字、変数が存在しない場合の代替出力、追加の修飾子を設定することができます。

### 変数セット

標準で使うような値については、`values`メソッドを使う事であらかじめ変数セットとして設定しておくことができます。

```:php
use fw3\strings\builder\StringBuilder;

$stringBuilder = StringBuilder::factory();
$stringBuilder->values([
    'default1' => '[default]',
]);

echo $stringBuilder->build('{:default1}はあります。');
// [default]はあります。と表示されます。
```

実行時に第二引数を与えることで、実行時のみ追加したい変数や、実行時のみ変数セットの値を上書きすることもできます。

```:php
use fw3\strings\builder\StringBuilder;

$stringBuilder = StringBuilder::factory();
$stringBuilder->values([
    'default1' => '[default]',
    'value1'   => 'AAAA',
]);

echo $stringBuilder->build('{:default1}はあります。{:value1}や{:value2}もあります。', [
    'value1'   => 'BBBB',
    'value2'   => 'CCCC',
]);
// [default]はあります。BBBBやCCCCもあります。と表示されます。

echo $stringBuilder->build('{:default1}はあります。{:value1}もあります。');
// [default]はあります。AAAAもあります。と表示されます。
```

現在、変数セットに登録されている値は`values`メソッドで取得することができます。

```:php
use fw3\strings\converter\Convert;
use fw3\strings\builder\StringBuilder;

$stringBuilder = StringBuilder::factory();
$stringBuilder->values([
    'default1' => '[default]',
]);

echo Convert::toDebugString($stringBuilder->values(), 1);
// ['default1' => '[default]']と表示されます。
```

### 変数部の指定文字

現在の環境に合わせた変数部のエンクロージャを指定する事もできます。

```:php
use fw3\strings\builder\StringBuilder;

$stringBuilder = StringBuilder::factory();
$stringBuilder->enclosure('{{', '}}');

echo $stringBuilder->build('{{default1}}はあります。{:default1}はありません。', [
    'value1'   => 'BBBB',
]);
// BBBBはあります。{:default1}はありません。と表示されます。
```

### 変数が存在しない場合の代替出力

変数が存在しない場合、標準では変数名をそのまま出力します。
開発中は問題の検出がしやすくてよいのですが、本番では問題になります。

そういった場合のために変数が存在しない場合の代替出力を設定できます。

```:php
use fw3\strings\builder\StringBuilder;

$stringBuilder = StringBuilder::factory();
$stringBuilder->substitute('');

echo $stringBuilder->build('{:default1}はあります。{{default1}}はありません。', [
    'value1'   => 'BBBB',
]);
// BBBBはあります。はありません。と表示されます。

$stringBuilder->substitute('■■■■');

echo $stringBuilder->build('{:default1}はあります。{{default1}}はありません。', [
    'value1'   => 'BBBB',
]);
// BBBBはあります。■■■■はありません。と表示されます。
```

### 追加の修飾子

標準の修飾子に加え、追加の修飾子を設定することができます。

修飾子は`\fw3\strings\builder\modifiers\ModifierInterface`を実装したクラスまたはオブジェクト、あるいは`\fw3\strings\builder\modifiers\ModifierInterface`で定義される`__invoke`と同じインターフェースを実装した`\Closure`インスタンスを指定することができます。

```:php
use fw3\strings\builder\StringBuilder;
use fw3\strings\builder\modifiers\ModifierInterface;
use fw3\strings\builder\modifiers\ModifierTrait;

class ToUpper implements ModifierInterface
{
    use ModifierTrait;

    /**
     * 置き換え値を修飾して返します。
     *
     * @param   mixed   $replace    置き換え値
     * @param   array   $parameters パラメータ
     * @param   array   $context    コンテキスト
     * @return  mixed   修飾した置き換え値
     */
    public static function modify($replace, array $parameters = [], array $context = [])
    {
        return strtoupper($replace);
    }
}

$stringBuilder = StringBuilder::factory();
$stringBuilder->modifierSet([
    'to_upper'  = > 
    'to_lower'  = > function ($replace, array $parameters = [], array $context) {
        return strtolower($replace);
    },
]);

echo $stringBuilder->build('{:default1|to_upper}と{:default1|to_lower}に変化します。', [
    'value1'   => 'AbCd',
]);
// ABCDとabcdに変化します。と表示されます。
```

## おまけ：変数情報展開

変数に関する情報を文字列にします。

変数が実際はどういう状態になっているかをさっと見たりログに残したりする場合に便利です。

配列などの階層構造になっている値は指定した深さまでは表示するように制約できます。

実際に感謝されたケースはfalseやnullなどの文字列化した場合に空文字となってしまった場合や、数値が文字列か整数かを簡単に識別できた場合などでした。

```:php
use fw3\strings\converter\Convert;

echo Convert::toDebugString(true); // true と表示されます
echo Convert::toDebugString(false); // false と表示されます
echo Convert::toDebugString(null); // null と表示されます

echo Convert::toDebugString(0.0); // 0.0 と表示されます
echo Convert::toDebugString(0.1); // 0.1 と表示されます
echo Convert::toDebugString(0); // 0 と表示されます

echo Convert::toDebugString('0'); // '0' と表示されます

echo Convert::toDebugString([0 => [], 'a' => [1, 2]]); // Array と表示されます
echo Convert::toDebugString([], 1); // [0 => Array, 'a' => Array] と表示されます

echo Convert::toDebugString(new stdClass()); // object((stdClass)#381) と表示されます #381の箇所は実行環境により異なります
```