从关系到最后的条件

时间:2018-11-30 09:51:53

标签: php laravel eloquent one-to-many laravel-5.7

我有两个关系一对多的表。我的任务很简单,我需要关联条件表中的每个父项最后一个条件。

第一个表为状态:

async function updateUuid() {
  try {
    const users = await Users.find({});
    for (const user of users) {
      const uuid = uuid();
      await User.findByIdAndUpdate(user._id, { $set: { newId: uuid } });
    }
  } catch (e) {
    console.error(e);
  }
}

关系是

| id | partner_id | status | created_at          |
|----|------------|--------|---------------------|
| 1  | 1          | 1      | 2018-01-01 00:00:00 |
| 2  | 1          | 5      | 2018-02-01 00:00:00 |
| 3  | 2          | 1      | 2018-01-01 00:00:00 |

第二个伙伴:

public function partner()
{
    return $this->belongsTo(Partner::class, 'partner_id');
}

关系是

| id | name      |
|----|-----------|
| 1  | partner_1 |
| 2  | partner_2 |

假设我想让所有合作伙伴的最近状态为1。我尝试过:

public function status()
{
    return $this->hasMany(Status::class, 'partner_id')->orderBy('id', 'desc');
}

结果是这样的:

Partner::with('status')
    ->whereHas('status', function ($query) use ($status) {
          $query->where('status', $status);
       })
    ->get();

但是有了它,即使他的最后一个状态为5,但我也会得到partner_1,但历史上他的状态为1。

我创建了sql查询来获取此信息,但是我认为完成这样一个简单的任务相当复杂。而且我认为必须有一些简单的Laravel方法:

"select * from `partners` where exists (select * from `status` where `partners`.`id` = `status`.`partner_id` and `status` = 1)"

我的目标是只获得partner_2,因为只有他的最后状态为1。

2 个答案:

答案 0 :(得分:0)

一种方法是自定义关系方法以包括一些排序(如@ yrv16所建议)

但是,要提高效率,最好的方法是子查询。一个非常good article by J. Reinink的人很好地解释了这一点。

简而言之,是这样的:

class Partner extends Model {

    // ...

    public function scopeWithLastStatus($query)
    {
        $query->addSubSelect('last_status', Status::select('status')->latest());
    }

    // ...

这会将“虚拟”属性last_status添加到模型中。

然后您可以执行以下操作:

Partner::withLastStatus()->get()->where('last_status', 'idle');

答案 1 :(得分:0)

您可以使用此:

Partner::select('partners.*')
    ->join('status', 'partners.id', 'status.partner_id')
    ->where('status.status', $status)
    ->where('status.id', function($query) {
        $query->select('id')
            ->from('status')
            ->whereColumn('partner_id', 'partners.id')
            ->orderByDesc('id')
            ->limit(1);
    })->get();