Collection::wrap

Wraps a scalar, array or existing collection in a collection without ever nesting one inside another.

Signature
public static function wrap(mixed $value): static
  • Added in Laravel 5.5

Parameters

ParameterTypeDescription
$valueiterable|mixedThe 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

  • null becomes an empty collection, not [null]. It delegates to Arr::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. Use flatten() 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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.

Example · php
<?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";                            // 0

wrap 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.

Example · php
<?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

  • Be the first to comment on this lesson.