Laravel (eloquent) 存取器:只计算一次

Laravel (eloquent) accessors: Calculate only once

我有一个 Laravel 模型,它有一个计算访问器:

Model Job 有一些 JobApplicationsUser 相关联。 我想知道用户是否已经申请了工作。

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

有没有easy方法只计算访问器一次

/**
 * 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();
}

提前致谢。

我会在您的 User 模型上创建一个方法,您将 Job 传递给该方法,并 returns 一个关于用户是否已应用的布尔值:

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);

正如评论中所建议的那样,一点也不棘手

 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;
    } 

}

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

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第一次访问时会returnnull,这会导致?:的下一段被执行。 array_set 会将评估值设置为 'user_applied' 键。在随后的调用中,array_get 将 return 先前设置的值。

这种方法的 额外优势 是,如果您在代码中的某处设置了 user_applied(例如 Auth::user()->user_applied = true),它将反映出,这意味着它将 return 该值而不做任何额外的事情。