简体   繁体   中英

How to return a single model in Laravel from a hasManyThrough eloquent relationship

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;

Question 1

Is my hasManyThrough relationship correct, or have I overcomplicated things here?

Question 2

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM