mamaye
mamaye

Reputation: 1054

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.

Upvotes: 16

Views: 21232

Answers (4)

Sesha
Sesha

Reputation: 318

// 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();
}

Upvotes: 9

Dilip Hirapara
Dilip Hirapara

Reputation: 15296

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();

Upvotes: 5

lagbox
lagbox

Reputation: 50491

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.

Upvotes: 21

Dev256
Dev256

Reputation: 31

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

Upvotes: 0

Related Questions