Eloquent Polymorphic One Of Many
Jim O'Halloran • September 28, 2021
laravel phpEloquent in Laravel received a new "one of many" relationship type in Laravel 8.42. Laravel News explains this comparatively recent feature here.
It seems like the ideal use case for this is a one to many relationship, where one of the relations is a bit "special".
The examples in the linked Laravel News post are helpful, and include the case where a User has manu login sessions, but you use and want to access efficiently the "latest" login session.
The feature's PR shows this implemented as follows (and has other good info on the use case for this relation):
public function latest_login()
{
$this->hasOne(Login::class)->orderByDesc('id');
}
The feature's original author (Lennart Carstens-Behrens) also provides this helpful repo with models containing additional examples.
Use With Polymorphic Relationships
My application has a generic "address" entity, which can be related to a bunch
of different things via a polymorphic relationship. Addresses can be attached to
either Customers or Contacts for example. I call this relationship adressable
.
Each adressable
can have a bunch of different addresses, one of which is the
"primary" address. Rather than iterating the entire address book collection all
the time, I wanted to see if "One Of Many" could be used with a polymorphic
relationship to get the primary address.
Here's what I came up with:
public function primaryAddress()
{
return $this->morphOne(Address::class, 'addressable')
->ofMany(
['id' => 'max'],
function ($q) {
$q->where('primary', true);
}
);
}
This gets the last address (MAX(id)
) where the primary
field is set
to true
. The "last address" part is a bit redundant since in my case there
should only ever be a single primary address, but it's nice that the edge case
is handled in a consistent way.
All in all, this is a feature I see myself using a lot. The ability to put any arbitrary where conditions into the query builder makes it super versatile, and the fact that it plays nice with polymorphic relationships is just awesome!