an.leclerc's avatar

Latest record many to many relationship

Hi,

I have 3 tables :

  • dossier

    • id
  • status

    • id
  • dossier_statuses

    • dossier_id
    • status_id
    • created_at

I'd like to retrieve dossier where their last status saved is of a specific status (id).

I tried few things but it doesn't work. I get all dossier with this specific status but for some, this status is not the last.

If anybody can help me

0 likes
8 replies
enadabuzaid's avatar

Can you share the code you’ve tried so far? It’ll be easier to help you.

Glukinho's avatar

You need to define "has one of many" relation on Dossier model:

public function lastStatus(): HasOne
{
    return $this->hasOne(Status::class)->ofMany('created_at', 'max');
}

After that $dossier->lastStatus() will give you what you want.

https://laravel.com/docs/12.x/eloquent-relationships#has-one-of-many

Upd: if you need to query by particular status, then you should do so:

$dossier = Dossier::whereRelation('lastStatus', 'id', '=', $status_you_need_to_query_by)->first();
kevinbui's avatar

@Glukinho I don't think this is gonna work. Dossier and Status are like are many-to-many relationship, not a one-to-many relationship, so that cannot be transformed to a one-of-many one.

an.leclerc's avatar

In my dossier model I have :

public function dossierStatuses(): BelongsToMany
    {
        return $this->belongsToMany(StatusTypeModel::class, 'dossier_statuses', 'dossier_id', 'type_status_id')
            ->orderBy('dossier_statuses.created_at', 'desc')
            ->withTimestamps();
    }

I tried :

DossierModel::whereHas('dossierStatuses', function ($query) use ($status) {
                    $query
                        ->where('type_status_id', $status->id)
                        ->orderBy('dossier_statuses.created_at', 'DESC')
                    ;
                })

With this query, I have all the files with this status, but I would only like the files that have this status as the last status.

an.leclerc's avatar

@ghabe I have this error :

Unknown column 'dossier_statuses.created_at' in 'order clause' (Connection: mysql, SQL: select * from `dossier` where exists (select * from `type_status` inner join `dossier_statuses` on `type_status`.`id` = `dossier_statuses`.`type_status_id` where `dossier`.`id` = `dossier_statuses`.`dossier_id` and `type_status_id` = 16cd0f86-afc5-4a41-825a-58758743e970 and `type_status`.`deleted_at` is null) and `dossier`.`deleted_at` is null order by `dossier_statuses`.`created_at` desc, `dossier`.`updated_at` desc limit 1)
kevinbui's avatar
Level 41

The solution can be more straightforward and simpler than we all thought.

Let's ignore the relationships for now, we can write a database query using addSelect with dossier and and dosier_statuses tables only.

Dossier::addSelect(['last_status_id' => DB::table('dossier_statuses')->select('status_id')
    ->whereColumn('dossier.id', 'dossier_statuses.dossier_id')
    ->latest('dossier_statuses.id')
    ->limit(1)
])
    ->having('last_status_id', $yourSpecificStatusId)
    ->get();

Pls let me know if this works.

1 like
kevinbui's avatar

@an.leclerc Happy to help. If you are happy with my answer, pls mark it the best one to close this thread.

Please or to participate in this conversation.