简体   繁体   中英

Return the last record in a One to many Eloquent Relation using Laravel

Assuming there existed a One To Many relation where a User has Many Jobs, and the last record in the job table is the current job of the user. What is a better way of returning the users with their last jobs?

Here is what I have tried.

User Class

public function ejob(){
   return $this->hasMany(Ejob::class);
}

Ejob Class

public function user(){
   return $this->belongsTo(User::class);
}

API Controller Method

public function index()
{
  return UserResource::collection(( 
  User::with(
          $this->particulars() // I want the last record from this line
        )->orderBy('id', 'desc')->get() ));
}

Particulars Method

// I want the last record from this
private function particulars(){
        return 
        [
            'ejob.company:id,name', 
            'ejob.job:id,title', 
            'ejob.department:id,name',
            'ejob.reporting:id,surname,first_name,other_name',
            'ejob.employmentstatus:id,name', 
            'country:id,name', 
            'gender:id,name', 
            'state:id,name'
        ];
}

User Resource

public function toArray($request)
    {
        //return parent::toArray($request);
        return [
            'data' => [
                'id' => $this->id,
                'surname' => $this->surname,
                'first_name' => $this->first_name,
                'other_name' => $this->other_name,
                'email' => $this->email,
                'phone_number' => $this->phone_number,
                'birthday' => $this->birthday->format('d-m-Y'),
                'age'=> $this->birthday->age,
                'ejob' => $this->whenLoaded('ejob'),
        ];
    }

Currently, this returns a user with all related records from the ejobs table but I want just the last job.

You could define another relationship method for the same relationship but define it as a Has One instead of a Has Many:

public function currentJob()
{
   return $this->hasOne(Ejob::class, ...)->latest();
   // order by by how ever you need it ordered to get the latest
}

Then you could eager load that instead of the ejob relationship where needed.

You can use first() instead of get() . So it'll get a single model instance. get() method give a collection and first() method give you a single model instance.

User::with(
          $this->particulars()
        )->orderBy('id', 'desc')->first()

Or you can use latest() to get the last inserted record.

User::with(
          $this->particulars()
        )->latest()->first()

->latest() fetches the most recent set of data from the Database. In short, it sorts the data fetched, using the created_at column to chronologically order the data.

Edit:-

As you wanted to get the last record of the relationship you can do as below.

User::with('ejob', function($query) {
    return $query->latest()->first();
})->get();
// in your case

public function currentJob()
{
   return $this->hasOne(Ejob::class, ...)->latestOfMany();
   // order by by how ever you need it ordered to get the latest
}

// another example 

public function latestPerformance()
{
    return $this->hasOne(Performance::class)->latestOfMany();
}

You can group it by GROUP BY and then return all results. There you will see job for each User

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