Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent collections methods such as only or except return an empty collection

From the docs, I have tested the following example with the ->only() method

$collection = collect(['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]);

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

and it is working indeed.

However, when I apply that method to a collection I get from the database (Model),

$myCollection = MyModel::orderBy('id','desc')->paginate(5);
$filtered=$myCollection->only(['id']);
        dd(filtered);

the collection returned is empty!

Collection {#199 ▼
  #items: []
}

If I dd($myCollection); the collection gotten from the database, it is indeed full of the appends, attributes, and so on stuff. The data appears correctly in the table blade view.

But if I apply either the ->only() or ->except() to $myCollection methods ... the returned collection is empty.

For example, this is the piece of the collection, where I only want to show the id attribute, for example, or some more but not all:

LengthAwarePaginator {#218 ▼
  #total: 3041
  #lastPage: 609
  #items: Collection {#219 ▼
    #items: array:5 [▼
      0 => MyModel {#220 ▼
        #dates: array:1 [▶]
        #appends: array:5 [▶]
        #connection: null
        #table: null
        #primaryKey: "id"
        #keyType: "int"
        #perPage: 15
        +incrementing: true
        +timestamps: true
        #attributes: array:12 [▼
          "id" => 3041
          "date" => "2017-01-25"
          "value1" => "12"
          "value2" => "20"
          "value3" => "22"
          "value4" => "25"
          "value5" => "46"
          "value6" => "48"
          "value7" => "50"
          "value8" => "$60,000,000.00"
          "created_at" => null
          "updated_at" => null
        ]

But when I apply ->only(['id']), the collection is returned empty.

I have tested it without the paginate and the problem of the empty collection is still the same, so I don't think it has to do with the LengthAwarePaginator.

Workaround Unfortunately I am achieving this the hard way:

    $filtered = collect(['id'=>$myCollection->pluck(['id']),'Value1'=>$myCollection->pluck('value1')]);
dd($filtered);

Now I am getting the desired collection where, for example I just want two attributes or columns from the database:

Collection {#212 ▼
  #items: array:2 [▼
    "id" => Collection {#201 ▶}
    "value1" => Collection {#211 ▶}
  ]
}

Why is this happening? What am I missing? How can I fix it?

like image 578
Pathros Avatar asked Feb 01 '17 04:02

Pathros


People also ask

What is eloquent Collection?

Eloquent collections are an extension of Laravel's Collection class with some handy methods for dealing with query results. The Collection class itself, is merely a wrapper for an array of objects, but has a bunch of other interesting methods to help you pluck items out of the array.

Which of the following methods on Collection will get all the records from it laravel?

Avg method provided by Laravel Collection returns the average value. By default, it will provide average of all the values in collection.

What are laravel collections?

Laravel collection is a useful feature of the Laravel framework. A collection works like a PHP array, but it is more convenient. The collection class is located in the Illuminate\Support\Collection location. A collection allows you to create a chain of methods to map or reduce arrays.


1 Answers

Take note that only() will return item(s) with the specified key which is applied to an array with keys or associative array. As example given, it is array with keys

['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]

However, if you test to use only() with collection from eloquent results, which contains an array of collections / objects (without key).

[ object, object, object ]

It will work if the collection contain keys.

[ 'product_id' => object, 'name' => object ]

Thus, in your case to filter only the values of specified keys, I suggest to use pluck() or map()

like image 57
xmhafiz Avatar answered Sep 19 '22 17:09

xmhafiz