Laravel范围使用计算值

时间:2018-09-28 17:25:22

标签: php laravel laravel-5 eloquent laravel-5.4

我在Laravel 5.4中存在以下问题: 这里有一个用户表和一个成员资格表,一个用户可以拥有许多成员资格,而成员资格属于一个用户。成员资格是每年有效的,但是成员会为他们推荐在我的网站上注册的每个朋友获得额外的免费日,因此免费日的数量在不断变化;这反过来改变了会员的有效期。 所以问题是:如果到期日期是变量,如何为给定用户划分活动成员资格? 我将需要执行以下操作:

首先在Membership.php中过期:

这将计算每个成员的总天数:    请注意,friendsDays是根据User.php中的每个用户计算的。

public function getTotalDaysAttribute() {
        $days = $this->paidDays + $this->user->friendsDaysRemaining;
        return $days;
    }

这将计算每个会员的到期日期:

public function getExpirationDateAttribute() {
    $date = $this->startDay->addDays($this->TotalDays);
    return $date;
}

到目前为止很好...现在,这就是我遇到的问题(伪代码):

public function scopeActive($query, $dateToCheck = Null) {
   $query->where($dateToCheck >= $this->expirationDate);
}

如何正确编码以获取:

dump($user->membership()->active()->get());

谢谢。

4 个答案:

答案 0 :(得分:1)

您有两个问题:

  1. 您正在尝试在范围中使用模型值。范围在设置模型值之前发生。这是因为要获取要设置的模型中的值,必须首先执行获取数据的查询。

  2. 不幸的是,由于您的数据库设计,您将无法创建范围以获取所需的答案。这是因为您正在使用其他表上的值来计算int weight = Integer.parseInt(args[0]); int heightInInches = Integer.parseInt(args[1])*12 + Integer.parseInt(args[2]); bmi = ((weight * 703)/(heightInInches * heightInInches)); 值。

我建议您更改数据库中的TotalDays值,并在邀请朋友时调用它。

类似的东西:

expirationDate

答案 1 :(得分:0)

您可以将变量传递给作用域,例如,可以定义如下范围:

public function scopeActive($query, \Carbon\Carbon $dateToCheck = Null) 
{
   $query->where('some_date_field',  '>=' ($expirationDate ?? now())->toDateTimeString());
}

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

$dateToCheck = now()->addDays(30);

dump($user->membership()->active($dateToCheck)->get());

如果更方便使用,您还可以仅将天数而不是Carbon实例传递给作用域。

答案 2 :(得分:0)

使用您自己定义的API:

IMAGES_STORE

您的方法$user->membership()->active()->get(); 将无法查看计算到期日期所需的相关scopeActiveUser变量。您可以自己尝试:

friendsDaysRemaining

在您的位置上,我可能会在public function scopeActive($query) { var_dump($this->id); // null var_dump($this->user); // null, this part will try to do the query: select * from users where id = null } 表上保留expiration_date列,并在需要时进行更新。然后,您可以执行以下操作:

memberships

答案 3 :(得分:0)

谢谢你们的迅速回答。我根据您的想法采用了不同的方法。由于无法在查询中使用计算所得的字段,因此我返回了数据库中确实存在的字段,即renewalDueDate,即从付款日期算起的一年;两者都是已知日期和固定日期。然后,在查询中,我将$ user和$ dateToCheck作为参数传递,减去剩余的好友天数并与该值进行比较,如下所示:

public function scopeActive($query, $user, $dateToCheck = Null) {
    // If no date is passed, use today()
    $dateToCheck = is_null($dateToCheck) ? Carbon::today() : Carbon::parse($dateToCheck);

    //Substract the friendsDaysRemaining from the dateToCheck
    $AdjustedEndDate = $DateToCheck->copy()->subDays($user->friendsDaysRemaining);

    //Build the query 
    $query  ->where('paid', 1) //its been paid for
            ->where('startDay', '<=', $DateToCheck) //It has started
            ->where('renewalDueDate', '>=', $AdjustedEndDate); //It has not expired

    return $query;
}

尽管必须通过用户才能获得剩余的好友天数,但现在可以正常工作了:

$dateToCheck= '2018-09-01';
dump($user->membership()->active($user, $dateToCheck)->pluck('id'));

结果:

  

集合{#299▼#项目:数组:2 [▼       0 => 83       1 => 6]}

当然,您也可以通过$ friendsDaysRemaining而不是$ user进行传递,但是也不够优雅。

再次感谢。