Reputation: 8668
I've loaded a model along with a belongsToMany
relationship from my database:
$author = Author::with('publications')->first();
/** Returns something like:
{
"id": 3457,
"email": "[email protected]",
"publications": {
"1": {
"id": 240897,
"title": "Food left by other people at a restaurant - is it safe to eat? A comparative review.",
"journal": "Journal of Scrounging and Gleaning",
"year": 2007,
"pivot": {
"author_id": 3457,
"publication_id": 240897
}
},
"2": {
"id": 249196,
"title": "Stop picking at it - you'll leave a scar!",
"journal": "Proceedings of the International Conference on Nagging",
"year": 2008,
"pivot": {
"author_id": 3457,
"publication_id": 249196
}
}
}
}
*/
I then fetch some additional data for each publication
from a third-party API and merge it into my collection, which works fine.
However, I then want to sort the publications based on this third-party data, so I use a callback in sortByDesc
:
$sorted = $author->publications->sortByDesc(function ($publication, $key) {
// Blah blah blah not important how I sort
return $blah;
});
$author->publications = $sorted->values();
According to the docs for sortBy, I need to use values
if I want to renumber my results after sorting. $sorted->values()
does indeed seem to be a re-keyed, sorted list, but even after I assign it to $author->publications
, $author->publications
still has the old keys.
Even more strange is that just running sortByDesc
seems to sort the list in-place, even if I don't assign the result back to $author->publications
. Why can't I assign my re-keyed collection back to $author->publications
? I have a feeling that this has something to do with the nuances of relations versus attributes, but I don't know how to address this.
Upvotes: 0
Views: 52
Reputation: 8668
The problem is that when I assign the sorted collection to $author->publication
, I'm not actually overwriting the relation $author->publication
. Rather, I'm just adding a new attribute to $author
which also happens to be called publication
. Thus, my $author
object ends up looking something like this:
UserFrosting\Author Object
(
[timestamps] =>
[connection:protected] =>
[table:protected] => author
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[attributes:protected] => Array
(
[id] => 3457
[email] => [email protected]
[publications] => Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[0] => UserFrosting\Publication Object
(
[timestamps] =>
[connection:protected] =>
[table:protected] => publication
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[attributes:protected] => Array
(
[id] => 240897
[title] => Food left by other people at a restaurant - is it safe to eat? A comparative review.
[journal] => Journal of Scrounging and Gleaning
[year] => 2007
)
)
[1] => UserFrosting\Publication Object
(
[timestamps] =>
[connection:protected] =>
[table:protected] => publication
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[attributes:protected] => Array
(
[id] => 249196
[title] => Stop picking at it - you'll leave a scar!
[journal] => Proceedings of the International Conference on Nagging
[year] => 2008
)
)
)
)
)
[relations:protected] => Array
(
[publications] => Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[1] => UserFrosting\Publication Object
(
[timestamps] =>
[connection:protected] =>
[table:protected] => publication
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[attributes:protected] => Array
(
[id] => 240897
[title] => Food left by other people at a restaurant - is it safe to eat? A comparative review.
[journal] => Journal of Scrounging and Gleaning
[year] => 2007
)
)
[0] => UserFrosting\Publication Object
(
[timestamps] =>
[connection:protected] =>
[table:protected] => publication
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[attributes:protected] => Array
(
[id] => 249196
[title] => Stop picking at it - you'll leave a scar!
[journal] => Proceedings of the International Conference on Nagging
[year] => 2008
)
)
)
)
)
)
As you can see, relations
contains the sorted list of publications, but still retaining the original keys. attributes
contains the sorted and renumbered list. When I call $author->toArray()
, it is apparently using the relation rather than the attribute. The trick, therefore, is to force Eloquent to assign my renumbered collection to the relation:
$author->setRelation('publications', $sorted->values());
Upvotes: 1