Laravel(eloquent)访问器:仅计算一次

4

我有一个Laravel模型,其中有一个计算的访问器:

模型Job有一些与User相关联的JobApplications。 我想知道用户是否已经申请了这个工作。

为此,我创建了一个名为user_applied的访问器,它获取当前用户的applications关系。这个方法可以正常工作,但是每次访问该字段时都会重新计算(进行查询)访问器。

有没有什么简单的方法只计算一次访问器?

/**
 * Whether the user applied for this job or not.
 *
 * @return bool
 */
public function getUserAppliedAttribute()
{
    if (!Auth::check()) {
        return false;
    }

    return $this->applications()->where('user_id', Auth::user()->id)->exists();
}

提前感谢。

3个回答

5

正如评论中所建议的,这并不是很棘手

 protected $userApplied=false;
/**
 * Whether the user applied for this job or not.
 *
 * @return bool
 */
 public function getUserAppliedAttribute()
{
    if (!Auth::check()) {
        return false;
    }

    if($this->userApplied){
        return $this->userApplied;
    }else{
        $this->userApplied = $this->applications()->where('user_id', Auth::user()->id)->exists();

        return $this->userApplied;
    } 

}


1
我会创建一个在你的User模型上的方法,你可以将Job传递给它,并返回一个布尔值,表示用户是否已经申请过该职位:
class User extends Authenticatable
{
    public function jobApplications()
    {
        return $this->belongsToMany(JobApplication::class);
    }

    public function hasAppliedFor(Job $job)
    {
        return $this->jobApplications->contains('job_id', $job->getKey());
    }
}

使用方法:

$applied = User::hasAppliedFor($job);

干杯。这个酷炫的解决方案肯定能解决这个问题。但如果有一种方法只计算访问器一次就好了... - josec89
您可以在模型上设置一个属性。然后在后续的调用中,检查该属性是否有值,如果有,则使用它;如果没有,则执行计算。 - Martin Bean
2
是的,那会起作用...相当棘手但会奏效。谢谢! - josec89
没问题。很高兴能帮忙! - Martin Bean

1

您可以将user_applied值设置到model->attributes数组中,并在下次访问时从属性数组返回它。

public function getUserAppliedAttribute()
{
    $user_applied =  array_get($this->attributes, 'user_applied') ?: !Auth::check() && $this->applications()->where('user_id', Auth::user()->id)->exists();
    array_set($this->attributes, 'user_applied', $user_applied);
    return $user_applied;
}
array_get 在第一次访问时返回 null,将导致执行 ?: 的下一个操作。 array_set 将计算出的值设置为 'user_applied' 键的值。在后续调用中,array_get 将返回先前设置的值。
这种方法的额外优势是,如果您在代码中的某个地方设置了 user_applied(例如Auth::user()-> user_applied = true),它将反映该值,这意味着它将返回该值而不执行任何其他操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接