Collection::wrap
Wraps a scalar, array or existing collection in a collection without ever nesting one inside another.
public static function wrap(mixed $value): static- Added in Laravel 5.5
Parameters
| Parameter | Type | Description |
|---|---|---|
$value | iterable|mixed | The value to wrap. May be a scalar, an object, an array, or something already implementing Illuminate\Support\Enumerable. |
Return value
staticA new instance of the class the method was called on. An Enumerable is re-wrapped from its items, an array is adopted as-is with its keys, anything else becomes a single-item collection, and null becomes an empty collection.
Changelog
- PHP 5.5Added as a static method on Collection, alongside the matching unwrap().
- PHP 6.0Moved to the EnumeratesValues trait, so LazyCollection::wrap() became available and returns a LazyCollection.
Collection::wrap is the normaliser you put at the top of a method that accepts "one thing, several things, or something that is already a collection". A scalar or object becomes a one-item collection, an array is adopted as-is, and an existing Enumerable is re-wrapped from its items rather than being nested inside a new one.
When to reach for it
Any public API typed Model|iterable, any config value a user may write as a string or a list, any argument you want to iterate over unconditionally. It removes the is_array($x) ? $x : [$x] dance from the top of the method.
What trips people up
nullbecomes an empty collection, not[null]. It delegates toArr::wrap, which special-cases null. Usually convenient, occasionally surprising when a null argument silently produces zero iterations instead of one.- It is not recursive.
Collection::wrap([[1, 2]])is a one-item collection holding an array. Useflatten()if you wanted it levelled. - Associative arrays keep their keys, so the result is not guaranteed to be a zero-indexed list. Add
values()if you need one. - Late static binding applies. Call it on the class you want back:
LazyCollection::wrap()returns a LazyCollection, and a Collection subclass returns itself.
Compared with collect(), the results are usually identical; wrap is the one that preserves the subclass and reads as intent.
Example
When to use it
- Let a notification or sync method accept a single model, an Eloquent collection, or a plain array of ids.
- Normalise a config value that users may write as either 'admin' or ['admin', 'editor'].
- Turn a possibly-null relation accessor into something safe to loop over.
- Wrap a value inside a macro or trait where the concrete collection subclass must be preserved.
Frequently asked questions
What does Collection::wrap(null) return?
An empty collection, not a collection containing null, because wrap delegates to Arr::wrap which treats null as nothing. Use collect([$value]) if the null must be preserved as an item.
What is the difference between Collection::wrap and collect()?
For most inputs they produce the same result, but wrap uses late static binding, so calling it on LazyCollection or a Collection subclass returns that class rather than a plain Illuminate\Support\Collection.
Does Collection::wrap flatten nested arrays?
No. wrap only adds at most one level and never removes one, so Collection::wrap([[1, 2]]) is a single-item collection holding the array [1, 2]. Call flatten() if you want it levelled.
More examples
Normalising a flexible argument
One code path handles four shapes of input. The last line is the behaviour to remember: a null argument produces an empty result rather than [null], so downstream code sees zero tags instead of one bogus one. The values() call is there because wrap preserves keys when the input was an associative array.
<?php
use Illuminate\Support\Collection;
function tagIds(mixed $tags): array
{
return Collection::wrap($tags)
->map(fn ($tag) => is_array($tag) ? $tag['id'] : $tag)
->values()
->all();
}
echo json_encode(tagIds(5)), "\n"; // [5]
echo json_encode(tagIds([5, 6])), "\n"; // [5,6]
echo json_encode(tagIds(collect([['id' => 5]]))), "\n"; // [5]
echo json_encode(tagIds(null)), "\n"; // []Accepting one model or a whole result set
A single User model is not an Enumerable and not an array, so it becomes a one-item collection; the Eloquent collection returned by get() is re-wrapped from its items rather than nested. The method body never branches on the argument type. This example needs a booted application and a database, so it is shown rather than run.
<?php
use App\Models\User;
use App\Notifications\GenericMessage;
use Illuminate\Support\Collection;
class Dispatcher
{
public function send(User|iterable $recipients, string $message): int
{
return Collection::wrap($recipients)
->each(fn (User $user) => $user->notify(new GenericMessage($message)))
->count();
}
}
$dispatcher = new Dispatcher;
echo $dispatcher->send(User::find(1), 'Hi'), "\n"; // 1
echo $dispatcher->send(User::where('vip', true)->get(), 'Hi'), "\n"; // 12
echo $dispatcher->send([], 'Hi'), "\n"; // 0wrap and unwrap as a round trip
unwrap is the inverse: it returns ->all() for an Enumerable and hands anything else back untouched. Note the pair is not symmetrical — wrap('plain string') gives a one-item collection, but unwrapping that gives ['plain string'], not the original scalar.
<?php
use Illuminate\Support\Collection;
$wrapped = Collection::wrap(['a' => 1, 'b' => 2]);
echo json_encode($wrapped->all()), "\n";
// {"a":1,"b":2}
echo json_encode(Collection::unwrap($wrapped)), "\n";
// {"a":1,"b":2} -- back to a plain array
echo json_encode(Collection::unwrap('plain string')), "\n";
// "plain string" -- non-collections pass straight through
Discussion