First of all let me apologize if this is incorrect, but have been already a few days trying to figure out this in forums and chats, and haven't been able and i want to confirm wether is an issue in the framework or not.
Using Resource collections, I have a collection with two items from my Ingredient model, as you can see the items are actually the same one.
Collection {#1126 â–¼
#items: array:2 [â–¼
0 => Ingredient {#1014 â–¼
+translatedAttributes: array:1 [â–¶]
#cascadeDeletes: array:1 [â–¶]
#fillable: array:1 [â–¶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [â–¶]
#original: array:7 [â–¼
"id" => 16
"code" => "odio"
"created_at" => "2018-07-01 13:49:59"
"updated_at" => "2018-07-01 13:49:59"
"deleted_at" => null
"pivot_dish_id" => 1
"pivot_ingredient_id" => 16
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [â–¶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [â–¶]
#defaultLocale: null
#forceDeleting: false
}
1 => Ingredient {#1119 â–¼
+translatedAttributes: array:1 [â–¶]
#cascadeDeletes: array:1 [â–¶]
#fillable: array:1 [â–¶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [â–¶]
#original: array:7 [â–¼
"id" => 16
"code" => "odio"
"created_at" => "2018-07-01 13:49:59"
"updated_at" => "2018-07-01 13:49:59"
"deleted_at" => null
"pivot_dish_id" => 2
"pivot_ingredient_id" => 16
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [â–¶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [â–¶]
#defaultLocale: null
#forceDeleting: false
}
]
}
I supposed from when I looked into the Collection class that the unique() method would return the unique items, from the collection array, but when I call the method on that collection object $ingredients->unique(), I keep getting both elements in the collection.
Again at this point, I'm not sure if I'm assuming incorrectly, or this is something that is actually not working as expected, have pasted the entire JSON of the object, in case you see there is something that I'm missing.
Really sorry if this is not a real issue and I make you lose time, will try to explain how i get to this point in the steps to reproduce.
I'm creating something similar to what is in https://github.com/developerdino/example-articles-api
Articles -> Dishes
Comments -> Ingredients
Some dishes will have the same ingredients, therefore I'm trying to not repeat them as part of the includes of the response object which is done I believe in the following file https://github.com/developerdino/example-articles-api/blob/master/app/Http/Resources/ArticlesResource.php when we are merging the collections $included = $authors->merge($comments)->unique();
That is where I'm expecting to filter out the duplicate items in the collection, from what I see in the ValueRetriever method in the Collections class, we are not retrieving the original property of the object, therefore I'm not 100% sure if this the intended behavior or not of the method, thanks!
What's the result of dd(get_class($ingredients));?
result of that is the following: "IlluminateSupportCollection"
Use this:
(new \Illuminate\Database\Eloquent\Collection($ingredients))->unique();
There are two Collection classes in Laravel:
Illuminate\Support\Collection and Illuminate\Database\Eloquent\Collection
The first one is the base class for the second one. When you fetch models from the database, you receive a collection of the second class. Certain methods (e.g. pluck()) convert this collection to the base class.
The second class uses the models' primary key to remove duplicates (the behavior you are expecting).
The first class, however, compares the actual values. This is where your models are not the same: They have the same id, but the PHP objects are different (#1014 vs #1119).
That worked perfectly, thanks for your help @staudenmeir
Sorry for having wasted your time, I thought for a minute this could be some sort of issue I was running into, thanks once again. Let me know if you want me to close this issue.
Thanks!
You're welcome. Yes, please close the issue.
You can also pass a key attribute to the unique call.
$fetched->unique('id');
To me it looks cleaner than passing that huge namespace class.
@hvlucas that works fine as well, thanks!
Most helpful comment
Use this:
There are two
Collectionclasses in Laravel:Illuminate\Support\CollectionandIlluminate\Database\Eloquent\CollectionThe first one is the base class for the second one. When you fetch models from the database, you receive a collection of the second class. Certain methods (e.g.
pluck()) convert this collection to the base class.The second class uses the models' primary key to remove duplicates (the behavior you are expecting).
The first class, however, compares the actual values. This is where your models are not the same: They have the same
id, but the PHP objects are different (#1014vs#1119).