I have the following table structure:
tickets
- id
assignments
- id
- ticket_id
- staff_id
- role
- isAssigned
staff
- id
- username
I have created a hasManyThrough
relationship on the tickets
model which successfully returns all the staff
associated with the ticket
through the assignments
table.
public function staff()
{
return $this->hasManyThrough(Staff::class, Assignment::class);
}
The assignments
table can hold 1 or more records for a ticket
for the same role
where the isAssigned
flag specifies whether the staff
association is active. As such only 1 record for a given role
will ever have isAssigned = 1
I make use of query scopes
to limit the results returned by the hasManyThrough
relationship, for example:
public function scopeWithAssignedEngineer($builder)
{
$filter = function ($staff) {
$staff->where([['isAssigned', 1], ['role', 'engineer']]);
};
return $builder->whereHas('staff', $filter)->with(['staff' => $filter]);
}
So if I call Ticket::withAssignedEngineer()->where('id', 123)->get();
I get my ticket along with the assigned engineer however, the engineer is a collection rather than an item.
ticket: {
id: 123,
assigned_engineer: [
{
...
}
]
}
When using the response I can call $ticket->assignedEngineer->first()
to get the engineer, however, I would prefer to not have to call first on every such collection.
So;
Is my hasManyThrough
relationship correct, or have I overcomplicated things here?
Is there something I can on or to my scopes
which work on hasMany
relationships that will only return a single item
inside the collection
so that I do not have to call ->first()
each time?
Not the most elegant solution, but it works.
Change assignedEngineer
to assignedEngineers
and add an accessor to the Ticket
model:
public function getAssignedEngineerAttribute() {
return $this->assignedEngineers->first();
}
Then you can get a single Staff
model like this:
$ticket->assignedEngineer
If you're returning a JSON response, add this to Ticket
:
protected $appends = ['assignedEngineer'];
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.