77

How do we create a new Eloquent Collection in Laravel 4, without using Query Builder?

There is a newCollection() method which can be overridden by that doesn't really do job because that is only being used when we are querying a set result.

I was thinking of building an empty Collection, then fill it with Eloquent objects. The reason I'm not using array is because I like Eloquent Collections methods such as contains.

If there are other alternatives, I would love to hear them out.

Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
JofryHS
  • 5,804
  • 2
  • 32
  • 39

9 Answers9

142

It's not really Eloquent, to add an Eloquent model to your collection you have some options:

In Laravel 5 you can benefit from a helper

$c = collect(new Post);

or

$c = collect();
$c->add(new Post);

OLD Laravel 4 ANSWER

$c = new \Illuminate\Database\Eloquent\Collection;

And then you can

$c->add(new Post);

Or you could use make:

$c = Collection::make(new Post);
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
  • 4
    Almost working! I think `\Illuminate\Support\Collection` is a more generic version of `\Illuminate\Database\Eloquent\Collection`. So I guess, it is part of Eloquent after all. Hope this helps others. – JofryHS May 12 '14 at 05:03
  • Yeah, I should have take a look at it, because I was missing the add method, which is present only in Eloquent\Collection. Edited. – Antonio Carlos Ribeiro May 12 '14 at 13:16
  • 1
    @JofryHS If using `\Illuminate\Support\Collection`, you could use `$c->push(new Post);` instead of the add method. – Rogier Feb 17 '16 at 16:22
  • I prefer to use the static method: `$c = \Illuminate\Database\Eloquent\Collection::make();`. This ensures proper factory instantiation. – Soulriser Dec 02 '16 at 18:34
  • Make does exactly the same: `return new static($items);` – Antonio Carlos Ribeiro Dec 02 '16 at 19:54
  • What If I need to wrap an array and then save it to DB. By wrapping it with Support\Collection I can't for example go foreach to save each element. How to convert it to Eloquent\Collection then? – Sabine Feb 18 '17 at 11:29
  • 1
    `Illuminate\Database\Eloquent\Collection` is not the same as `\Illuminate\Support\Collection`. The first have specific methods for working with Models – Javis Jun 25 '19 at 16:52
15

As of Laravel 5. I use the global function collect()

$collection = collect([]); // initialize an empty array [] inside to start empty collection

this syntax is very clean and you can also add offsets if you don't want the numeric index, like so:

$collection->offsetSet('foo', $foo_data); // similar to add function but with
$collection->offsetSet('bar', $bar_data); // an assigned index
Mr.Web
  • 6,992
  • 8
  • 51
  • 86
Gokigooooks
  • 794
  • 10
  • 20
11

I've actually found that using newCollection() is more future proof....

Example:

$collection = (new Post)->newCollection();

That way, if you decide to create your own collection class for your model (like I have done several times) at a later stage, it's much easier to refactor your code, as you just override the newCollection() function in your model

Mr.Web
  • 6,992
  • 8
  • 51
  • 86
Samuel Cloete
  • 332
  • 2
  • 9
7

Laravel >= 5.5

This may not be related to the original question, but since it's one of the first link in google search, i find this helpful for those like me, who are looking for how to create empty collection.

If you want to manually create a new empty collection, you can use the collect helper method like this:

$new_empty_collection = collect();

You can find this helper in Illuminate\Support\helpers.php

snippet:

if (! function_exists('collect')) {
    /**
     * Create a collection from the given value.
     *
     * @param  mixed  $value
     * @return \Illuminate\Support\Collection
     */
    function collect($value = null)
    {
        return new Collection($value);
    }
}
Mr.Web
  • 6,992
  • 8
  • 51
  • 86
chebaby
  • 7,362
  • 50
  • 46
  • For the record, mention of the `collect()` helper was already edited into the accepted answer 2 years before you posted this answer. – miken32 Jun 19 '19 at 18:11
  • 2
    is it possible to make an empty collection of type `Illuminate\Database\Eloquent\Collection`? – Connor Leech Dec 04 '20 at 23:55
5

Just to add on to the accepted answer, you can also create an alias in config/app.php

'aliases' => array(

    ...
    'Collection'      => Illuminate\Database\Eloquent\Collection::class,

Then you simply need to do

$c = new Collection;
andrewtweber
  • 24,520
  • 22
  • 88
  • 110
3

In Laravel 5 and Laravel 6 you can resolve the Illuminate\Database\Eloquent\Collection class out of the service container and then add models into it.

$eloquentCollection = resolve(Illuminate\Database\Eloquent\Collection::class);
// or app(Illuminate\Database\Eloquent\Collection::class). Whatever you prefer, app() and resolve() do the same thing.

$eloquentCollection->push(User::first());

For more information about understanding resolving objects out of the service container in laravel take a look here: https://laravel.com/docs/5.7/container#resolving

Tom Headifen
  • 1,885
  • 1
  • 18
  • 35
  • This should 100% be the accepted answer. The other answers resolve to a support collection not an eloquent collection! – Connor Leech Dec 04 '20 at 23:57
3

I am using this way :

$coll = new Collection();
    
$coll->name = 'name';
$coll->value = 'value';
$coll->description = 'description';

and using it as normal Collection

dd($coll->name);

Hyzyr
  • 568
  • 4
  • 13
1

It is better to use the Injection Pattern and after $this->collection->make([]) than new Collection

use Illuminate\Support\Collection;
...
// Inside of a clase.
...
public function __construct(Collection $collection){
    $this->collection = $collection;
}

public function getResults(){
...
$results = $this->collection->make([]);
...
}
Victor Aguilar
  • 455
  • 4
  • 18
0

What worked for me was to name the use namespace and instantiate it directly:

use Illuminate\Database\Eloquent\Collection as EloquentCollection;

# Usage
$this->latest_posts = new EloquentCollection();

Allowed me to merge two data subsets of eloquent collection results, this maintains the relationships - a regular collection (collect()) loses relationship and probably some more metadata.

$limit = 5;
$this->latest_posts = new EloquentCollection();

$pinned_posts = PinnedPostReference::where('category', $category)->get();
if($pinned_posts->count() > 0) {
    foreach($pinned_posts as $ppost) {
        $this->latest_posts->push($ppost->post);
    }
}

# Another Eloquent result set ($regular_posts)
foreach($regular_posts as $regular_post) {
    $this->latest_posts->push($regular_post);
}
Grant
  • 5,709
  • 2
  • 38
  • 50