🤖

nelmio/aliceのcurrentの使い方まとめ

2024/02/16に公開

nelmio/aliceのcurrent

nelmio/alice を使ってYAML形式でテストデータを記述する際、<current()> という組み込み関数を使うと繰り返しをシンプルに記述できて便利です。

App\Entity\Foo:
  foo{1..2}:
    currentValue: <current()> # '1', '2'

このように単純にインデックスの値をそのまま使いたい場合はよいのですが、インデックスの値を何かしら加工して使いたい場合には少し工夫が必要です。

intにキャストする

<current()> 関数は現在のインデックスを 文字列として返す ので、int しか渡せないプロパティなどに使う場合は適切にキャストする必要があります。

nelmio/alice には <intval()> という組み込み関数 があるので、以下のようにしてキャストできそうな気がしますが、実はこれは期待どおりに機能しません。

App\Entity\Foo:
  foo{1..2}:
    currentValueWithInt: <intval(current())> # 0, 0

この書き方だと <intval()> 関数の引数に <current()> 関数の結果を渡していることにはなっておらず、常に 0 が返ってきてしまいます。(詳しくコード追えていませんが、関数をネストするという使い方はできないということのようです)

期待どおりに機能させるには、以下のように書きます。

App\Entity\Foo:
  foo{1..2}:
    currentValueWithInt: <(intval($current))> # 1, 2

<()> の中に intval($current) が入っています。

この <()><identity()> という組み込み関数 のショートハンドで、引数として渡したものをPHPコードとして評価してくれるというものです。

なので、ここで引数に渡している intval($current) は、<intval()> 関数ではなく、PHPの intval() 関数というわけです。

$current は、<identity()> 関数の説明にもあるとおり <current()> 関数の戻り値と同じ値にアクセスできる組み込み変数です。

インデックスをずらして使う

<()> さえあればもはや何でもできますね。

例えば、{3..4} と付けたインデックスを、1 2 として使用したいような場合は、以下のように書けばよいです。

App\Entity\Foo:
  foo{1..2}:
    currentValue: <current()>

App\Entity\Bar:
  bar{1..2}:
    state: valid
    foo: '@bar<current()>' # '@bar1', '@bar2'
  bar{3..4}:
    state: invalid
    foo: '@bar<($current-2)>' # '@bar1', '@bar2'

インデックスの値をDateTimeなどに使う

さらに、DateTime などの日時の値にインデックスを使用するのも簡単です。

App\Entity\Foo:
  foo{1..2}:
    createdAt: <(new \DateTime("2024-$current-01"))> # \DateTime('2024-1-01'), \DateTime('2024-2-01')

ずらして使う場合はこんな感じです。

App\Entity\Foo:
  foo{3..4}:
    createdAt: <(new \DateTime(sprintf('2024-%02d-01', $current-2)))> # \DateTime('2024-01-01'), \DateTime('2024-02-01')

参考リンク

GitHubで編集を提案

Discussion