A repeat collection macro
A short time ago I had to add a placeholder item to a Laravel collection several times. I created a repeat macro to achieve this without breaking up the collection pipeline flow.
Collection::macro('repeat', function ($times, callable $callback) {
for ($i = 0; $i < $times; $i++) {
$callback($this);
}
return $this;
});
This was the first version and it allows you to write things like this:
collect([1, 2, 3])->repeat(3, function ($collection) {
$collection->prepend(null);
});
This adds null
3 times to the head of the collection: [null, null, null, 1, 2, 3]
. This implementation was sufficient for my needs, but I wanted to generalize it a bit to allow more flexibility.
Collection::macro('repeat', function ($times, callable $callback) {
if (is_callable($times)) {
$i = 0;
while ($times($this)) {
$callback($this, $i);
$i++;
}
return $this;
}
for ($i = 0; $i < $times; $i++) {
$callback($this, $i);
}
return $this;
});
Now $times
can be a callback which should return a boolean value. The abort condition can be specified based on the collection’s state. Every time $callback
is executed, $i
is passed to have access to the current iteration index.
collect([1, 2, 3])->repeat(function ($collection) {
return $collection->count() < 10;
}, function ($collection, $i) {
$collection->push($i);
});
So as long as the collection contains less than 10 items, new items are pushed to the collection.
You can use the pipe()
collection method for this task, too. But I wanted to have a short and elegant way to solve this problem without having to write a loop manually. If you like programming with collection pipelines, I hope you’ll enjoy this macro.