Php Laravel附加到模型的另一种方法

Php Laravel附加到模型的另一种方法,php,laravel,Php,Laravel,我正在建造一个api拉威尔。在我的消息模型中,我附加了以下内容: /** * @var array */ protected $appends = ['subscribed']; /** * @return mixed */ public function getSubscribedAttribute() { return $this->isSubscribedBy(); } IsSubscribedBy()生活在如下特征中: /** * @return mixed

我正在建造一个api拉威尔。在我的消息模型中,我附加了以下内容:

/**
 * @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();
}
/**
 * @return mixed
 */
public function index()
{
    return Message::orderBy('created_at', 'DESC')
        ->paginate(10);
}
public function isSubscribedBy()
{
    if(!Auth::check()) {
        return false;
    }
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
public function isSubscribedBy()
{
    return ($this->subscriptions->count() > 0);
}
这是可行的,但这样做会出现
n+1
问题,我无法使用
php artisan scout:import“App\messages\Message”
在algolia中加载消息,这显然会引发错误(因为没有人登录,但它正在找人:
Auth::user()->id):

[错误例外]
正在尝试获取非对象的属性

那么有更好的方法吗?我已经尝试过分形,但仍然存在
n+1
问题

---编辑---

我回来的时候是这样的:

/**
 * @return mixed
 */
public function isSubscribedBy()
{
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
/**
 * @return mixed
 */
public function index()
{
    return Message::orderBy('created_at', 'DESC')
        ->paginate(10);
}
public function isSubscribedBy()
{
    if(!Auth::check()) {
        return false;
    }
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
public function isSubscribedBy()
{
    return ($this->subscriptions->count() > 0);
}
因此,对于每条消息,它将执行此查询:

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

如果一个用户根本没有登录,那么很明显他们无法订阅。所以你可以这样做:

/**
 * @return mixed
 */
public function isSubscribedBy()
{
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
/**
 * @return mixed
 */
public function index()
{
    return Message::orderBy('created_at', 'DESC')
        ->paginate(10);
}
public function isSubscribedBy()
{
    if(!Auth::check()) {
        return false;
    }
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
public function isSubscribedBy()
{
    return ($this->subscriptions->count() > 0);
}
或者如果您需要
false
以外的内容,比如
null
只需返回该内容即可

好了,我们知道了如何快速加载它,首先需要将快速加载约束到当前用户:

return Message::orderBy('created_at', 'DESC')->with(['subscriptions'=> function ($query) {
    $query->where('user_id', '=', Auth::user()->id);
}])->paginate(10);
然后它只加载当前用户对消息的订阅。现在,在属性getter中,您需要访问已加载的集合,而不是雄辩的getter。您只需删除
订阅()
上的
()
,并使用收集方法而不是雄辩的方法(大多数情况下看起来完全相同)即可完成此操作。因此,您的函数可以如下所示:

/**
 * @return mixed
 */
public function isSubscribedBy()
{
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
/**
 * @return mixed
 */
public function index()
{
    return Message::orderBy('created_at', 'DESC')
        ->paginate(10);
}
public function isSubscribedBy()
{
    if(!Auth::check()) {
        return false;
    }
    return $this->subscriptions()
        ->where('user_id', Auth::user()->id)
        ->exists();
}
public function isSubscribedBy()
{
    return ($this->subscriptions->count() > 0);
}

希望这对您有效。

我会注入
用户id
,这样您就可以获得任何用户的订阅,而不仅仅是登录用户的订阅。我想可能您误解了我的问题。我需要来自已验证用户的订阅状态。如果我把
user\u id
发回去,我不知道用户是否订阅了。不,我没有误解。我的意思是,我不认为你应该使用它作为一个属性,我认为它应该是一个传递用户id的函数。因此,如果你在一个视图中,你需要检查登录用户是否已订阅,那么它将是
{{{$message->userSubscribed(Auth::user()->id)}
。我尽量避免在函数中使用全局状态,因为这会使单元测试变得非常困难。谢谢您的解释。我在问题中没有提到它是一个api(我在前端使用vue.js)。所以这是不可能的。(我改变了我的问题)我不确定algolia是什么,所以如果你必须将它作为一个属性,那么你可能需要首先检查用户是否未登录,并返回false,不管是否登录。谢谢,但我想我仍然有
n+1
问题。请看我上面的编辑。是的,我不确定你将如何解决这个问题,我需要看看你在哪里加载你的整个邮件列表。您可以正常使用即时加载来解决
n+1
问题。在我上面的编辑中,您可以看到我是如何发回消息的。你知道可以加载一个值吗?谢谢!!你真棒<代码>->withCount(['subscriptions'=>function($query){$query->where('user_id','=',Auth::user()->id);}])