Framework: GroupBy on Eloquent collection should return a regular collection (only() fails)

Created on 17 Jan 2016  路  1Comment  路  Source: laravel/framework

Just a small issue, but something I came across and wanted to highlight. In short, groupBy() on an \Illuminate\Database\Eloquent\Collection should return a new \Illuminate\Support\Collection so we can successfully call only() (and other methods) on it.


Say we get a set of models from the database which returns an \Illuminate\Database\Eloquent\Collection.

$media = File::all();

Then we want to groupBy() that collection, which returns a new Eloquent collection with the specified attributes as keys.

$media = $media->groupBy('groupkey');
"key1" => [
    "value",
    "value",
    "value"
],
"key2" => [
    "value",
    "value",
    "value"
],
"key3" => [
    "value",
    "value",
    "value"
],

Following that, we call $media->only(['key2', 'key3']) which throws a BadMethodCallException: Method getKey does not exist. as it tries to use the model's keys. Since we did a groupBy() there are no immediate models as child, only the keys we extracted.

If we put a toBase() in between, we get a regular collection and the result we expected, so why not return a regular collection in the first place?

$media->groupBy('groupkey')->toBase()->only(['key2', 'key3'])

Most helpful comment

This is because groupBy() (and basically all Collection methods) return a new staticdocs. This is done to ensure that all classes extending Illuminate\Support\Collection (like an Eloquent collection) can then continue to call methods of that child class.

In your case it is unfortunate because you want the functionality of the base collection instead of the Eloquent collection (overwritten only() method). I think ->toBase() is a good compromise to still be able to access functionality of the base (illuminate/support) collection.

Personally I don't think it should return a regular collection, because you would loose the ability to chain specific Eloquent collection methods after that.

>All comments

This is because groupBy() (and basically all Collection methods) return a new staticdocs. This is done to ensure that all classes extending Illuminate\Support\Collection (like an Eloquent collection) can then continue to call methods of that child class.

In your case it is unfortunate because you want the functionality of the base collection instead of the Eloquent collection (overwritten only() method). I think ->toBase() is a good compromise to still be able to access functionality of the base (illuminate/support) collection.

Personally I don't think it should return a regular collection, because you would loose the ability to chain specific Eloquent collection methods after that.

Was this page helpful?
0 / 5 - 0 ratings