Laravel - 从 Eloquent 模型中添加额外的 where 约束belongsToMany 关系

问题描述

我是 Laravel 的新手(使用 v7),所以如果我做错了,我深表歉意。 我为我的用户定制了订阅设置。

我有我的用户

id 名字 姓氏
1 约翰 能源部
2 能源部

我有我的订阅

id 姓名
1 基础
2 青铜
3 银色
4 黄金
5 白金

还有一个 subscription_user 数据透视表

id user_id subscription_id created_at expired_at
1 1 1 2021-02-01 23:22:12 2021-03-21 08:22:12
2 1 5 2021-03-21 08:22:12 2021-04-04 09:03:21
2 1 3 2021-04-04 09:03:21
2 2 1 2021-01-01 01:00:00 2021-01-05 05:30:00
2 2 2 2021-01-05 05:30:00 2021-01-06 08:34:10

因此,根据上述条目,John Doe 订阅了基本订阅,然后升级到白金,最后降级到白银。这是他目前的订阅

我有以下方法(在 User.PHP 中)首先获取用户订阅列表

public function subscriptions()
{
  return $this->belongsToMany('App\Subscription')
    ->orderby('pivot_created_at','desc')
    ->withPivot('created_at','expired_at')
    ->withTimestamps();
}

然后获取当前订阅

public function subscription()
{
  return $this->subscriptions->first();
}

但是,在某些情况下,用户的所有订阅都已过期,因此他们没有当前订阅。即在上述记录中 Jane Doe订阅了 2 个计划,但都已过期。

如果我在 Jane Doe 上调用 $user->subscription(),它仍然返回最新的过期条目。 我曾尝试将 where() 子句添加到我的 subscription 方法中,但没有效果

public function subscription()
{
  return $this->subscriptions->where('expired_at',NULL)->first();
}

有没有更好的方法来完成我想要实现的目标?我需要一种方法获取所有用户订阅,无论它们是活动的还是过期的。 (我有 - 这是最好的方法吗?)

但随后也获取不应始终包含 expired_at 的当前订阅。 看来我无法在 mt subscription 方法添加任何进一步的条件。

解决方法

您需要为订阅方法使用查询构建器,使用 subscriptions() 而不是集合 subscriptions

public function subscription()
{
  return $this->subscriptions()->whereNull('expired_at')->first();
}

调用 $this->subscriptions 等同于 $this->subscriptions = $this->subscriptions()->get()。其中 $this->subscriptions 返回一个集合。

$this->subscriptions(),使用该方法,返回一个查询构建器。

PS:它没有触发调用 first() 的错误,因为 Collection 也有一个名为 first() 的方法。