Skip to main content

SubForeachMapper

Applies its inner mappers to each element of an array (or Traversable) bindable value. Mappers::subForeach() takes Mapper or Validator arguments — the same arguments Mappers::pipe() accepts — and runs them as a pipe on every element individually. Each element is exposed as its own bindable, keyed by the array key.

It is applied with ->prop(...) (or ->props(...)). Only the elements present in the array are mapped; the array shape itself is preserved.

Mappers::subForeach() is the per-element companion to Mappers::subProps() (which maps the named children of a structure). It is typically followed by Mappers::subMerge() to reassemble the mapped elements into an array — the combination subForeach + subMerge + Mappers::value() is what TypedArrayUnmarshalTrait uses to build typed arrays of value objects. See UnmarshalMapper.

Example: transforming each element​

$src = new DataMap(['huii' => ['key1' => 'value1', 'key2' => 'value2']]);
$target = new DataMap();

Bind::attrs($src)->toAttrs($target)
->prop('huii', Mappers::subForeach(Mappers::value(fn (string $v) => $v . '-m')))
->exec();

echo $target->req('huii/key1'); // value1-m
echo $target->req('huii/key2'); // value2-m

Example: validating each element​

$result = Bind::attrs(['emails' => ['bad1', 'bad2']])
->prop('emails', Mappers::subForeach(Mappers::email()))
->toArray()
->exec();

// result is invalid with an error for each array element.
var_dump($result->isValid()); // false
var_dump($result->getErrorMap()->getChild('emails')->isEmpty()); // false
var_dump($result->getErrorMap()->getChild('emails')->getChild(0)->isEmpty()); // false
var_dump($result->getErrorMap()->getChild('emails')->getChild(1)->isEmpty()); // false