90

I'm trying to filter the following collection using the collection filter() method:

$collection = Word::all();

where the JSON output looks like this:

[
{
"id": "1",
"word": "dog",
"phonetic": "dog",
"mean": "pies",
"assoc": "some example text",
"author_id": "3",
"user_id": "3"
},
{
"id": "2",
"word": "sun",
"phonetic": "sun",
"mean": "słońce",
"assoc": "lorem ipsun dolor sit amet",
"author_id": "3",
"user_id": "2"
}, ...
]

However, when filtering the collection:

$filtered_collection = $collection->filter(function($item)
    {
        if($item->isDog())
        {
            return $item;
        }
 });

The filtered collection JSON output will look like this:

 {"1":
 {
 "id": "1",
 "word": "dog",
 "phonetic": "dog",
 "mean": "pies",
 "assoc": "some example text",
 "author_id": "3",
 "user_id": "3"
 },
 "2":
 {
 "id": "2",
 "word": "sun",
 "phonetic": "sun",
 "mean": "słońce",
 "assoc": "lorem ipsun dolor sit amet",
 "author_id": "3",
 "user_id": "2"
 }}

How can I keep the original JSON output when filtering a collection? I'd like to have an array of my Eloquent model instances when filtering the original collection.

starball
  • 20,030
  • 7
  • 43
  • 238
Tenzoru
  • 953
  • 1
  • 8
  • 9

4 Answers4

227

The collection's filter method calls array_filter on the underlying array, which, according to the PHP docs, preserves the array keys. This then results in your array being converted to a JavaScript object instead of an array.

Call values() on your collection to reset the keys on the underlying array:

$filtered_collection = $collection->filter(function ($item) {
    return $item->isDog();
})->values();

Side note: in newer versions of Laravel, you can use a higher order message to shorten the above into this:

$filtered_collection = $collection->filter->isDog()->values();
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
12

Just convert it to JSON with keeping in mind what the Laravel documentation states:

Note: When filtering a collection and converting it to JSON, try calling the values function first to reset the array's keys.

So the final code would be:

$filtered_collection->values()->toJson();
totymedli
  • 29,531
  • 22
  • 131
  • 165
  • 3
    Would the downvoter care to give an explanation? This is the correct answer which is totally the same than the accepted/upvoted other one which only was better worded. – totymedli Dec 15 '15 at 13:06
  • 5
    Downvoters are quick enough to downvote but never want to provide a reason – AdRock Aug 09 '18 at 18:05
0

Filtering from database could be done in this method also.

 //request the form value 
  $name=$request->name;
  $age=$request->age;
  $number=$request->phone;

 //write a query to filter
 $filter_result = DB::table('table_name')

 ->where('name', 'like', '%'.$name.'%')
 ->orWhere('age', 'like', '%'.$age.'%')
 ->orWhere('phone', 'like', '%'.$number.'%')

 ->get();

 if(is_null($filter_result)){
 return redirect()->back()->with('message',"No Data Found");

}else{
      return view('resultpage',compact('filter_result'));
}
0

If you have eloquent collection array and you want to filter it from some attribute, you can try following filter to achieve this.

In my case, $reports is variable contain eloquent collection object. and i want to filter from this collection with id attribute.

$filter_id = $reports->filter(function ($item) {
   return $item->id==5;
})->first();

now you have $filter_id variable that contains object with id=5.

you can access all attribute of id=5, like $filter_id->attribute_name.

Yuvraj Hinger
  • 198
  • 1
  • 6