我正在构建一个 api Laravel。在我的消息模型中,我附加了以下内容:
/**
* @var array
*/
protected $appends = ['subscribed'];
/**
* @return mixed
*/
public function getSubscribedAttribute()
{
return $this->isSubscribedBy();
}
IsSubscribedBy();
存在如下特征:
/**
* @return mixed
*/
public function isSubscribedBy()
{
return $this->subscriptions()
->where('user_id', Auth::user()->id)
->exists();
}
这是可行的,但这样做有 n + 1
问题,我无法使用 php artisan scout:import "App\Messages\Message"在 algolia 中加载消息
这显然会引发错误(因为没有人登录但它正在寻找某人:Auth::user()->id):
[ErrorException]
Trying to get property of non-object
那么有没有更好的方法呢?我已经尝试过分形,但我仍然遇到 n + 1
问题。
---编辑---
我是这样回来的:
/**
* @return mixed
*/
public function index()
{
return Message::orderBy('created_at', 'DESC')
->paginate(10);
}
因此对于每条消息,它将执行此查询:
$this->subscriptions()
->where('user_id', Auth::user()->id)
->exists();
最佳答案
如果用户根本没有登录,那么显然他们无法订阅。所以你可以这样做:
public function isSubscribedBy()
{
if(!Auth::check()) {
return false;
}
return $this->subscriptions()
->where('user_id', Auth::user()->id)
->exists();
}
或者,如果您需要 false
以外的东西,例如 null
,只需返回它即可。
确定了如何预先加载它,首先你需要将你的预先加载限制为当前用户:
return Message::orderBy('created_at', 'DESC')->with(['subscriptions'=> function ($query) {
$query->where('user_id', '=', Auth::user()->id);
}])->paginate(10);
然后它只急切地加载当前用户对消息的订阅。现在在您的属性 getter 中,您需要访问已经急切加载的集合,而不是 Eloquent getter。您只需删除 subscriptions()
上的 ()
并使用集合方法而不是 Eloquent 方法(大部分时间看起来完全相同)即可完成此操作。所以你的函数看起来像这样:
public function isSubscribedBy()
{
return ($this->subscriptions->count() > 0);
}
希望这对你有用。
关于php - Laravel 另一种附加到模型的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41698991/