Php Laravel雄辩的查询意外的结果

Php Laravel雄辩的查询意外的结果,php,mysql,laravel,laravel-5,eloquent,Php,Mysql,Laravel,Laravel 5,Eloquent,我发现一些查询结果确实出乎意料 它是拉威尔5.2 我们有以下实体: 用户方法: public function roles() : BelongsToMany { return $this->belongsToMany(Role::class)->withPivot('timestamp'); } 每个用户都可以有很多角色,所以我们也有角色实体(但在我的问题中这并不重要)和透视表用户角色,带有时间戳字段(当然还有ID),因为我们保存着关于时间的信息,当用户达到特定角色时 我

我发现一些查询结果确实出乎意料

它是拉威尔5.2

我们有以下实体:

用户
方法:

public function roles() : BelongsToMany
{
    return $this->belongsToMany(Role::class)->withPivot('timestamp');
}
每个
用户
都可以有很多角色,所以我们也有
角色
实体(但在我的问题中这并不重要)和
透视
用户角色
,带有
时间戳
字段(当然还有ID),因为我们保存着关于时间的信息,当
用户
达到特定角色时

我想获取所有
用户
及其最后分配的
角色

创建查询时(在某个存储库的
User
上下文中):

结果将包含
用户
,其内部有
角色
实体,按时间戳排序-没问题。但我只想在每个
用户
实体中检索最后一个角色,而不是所有有序

所以

然后我检索
用户
,但只有
用户
在最后一次包含它时获得了一些
角色
!所有其他
用户
角色
字段包含空数组

为什么对每个
用户
关系分别执行排序,但当我添加
限制
时,它的行为就像是对所有用户的全局限制

它让我发疯

谢谢你的建议

编辑 我已经创建了
lastRoles()
方法来获取所有
角色的有序描述。但是all,检索一个是不可能的

public function lastRoles() : BelongsToMany
{
    return $this->BelongsToMany(Roles::class)->withPivot('timestamp')->latest('timestamp');
}
以及测试:

$users = (new User())->with('lastRoles')->get();
但现在我必须迭代
用户
并对每个用户调用
lastRoles()

foreach ($users as $user) {
    var_dump($user->lastRoles()->get()->first()->name);
}
然后我检索分配给每个
用户的最新
角色的名称


所以。。。在one查询中无法执行此操作?这是唯一的方法?

当您急于加载带有查询约束的关系时,查询将运行一次以加载所有关系,而不是单独加载每个关系。这是预期的行为。想想看,为了优化性能,存在着将多个查询转换为一个查询的急切加载。只执行一个查询,因此您的
limit
约束将限制整个结果集,而不是基于每个模型

为了避免这种情况,您可以尝试创建另一个
belongtomany
方法来添加所需的限制约束。以下代码未经测试:

public function lastRole() : BelongstoMany
{
    return $this->belongsToMany(Role::class)
                ->withPivot('timestamp')
                ->orderBy('timestamp', 'desc')
                ->limit(1);
}
假设这样做有效,您只需将关系方法从
roles
更改为
lastRole
,并删除查询约束:

$this->with('lastRole')->all();

要使其工作,您需要一个助手函数:

public function latestRole()
{
 return $this->hasOne(Role::class)->withPivot('timestamp')->orderBy('timestamp', 'DESC');
}
然后:

$this->with('latestRole')->get();

这要归功于此。

我无法回答您的问题,但如果您仍然需要一种方法来获取最新的角色,您可能会发现此链接很有用:不确定这与我的答案有什么不同。也没有回答OP的问题。它为每个
用户提供所有
角色的降序排列,我只想为每个用户获取一个(最新的)。是否使用
$row->latestRole->somecolumn
检索它?因为它应该起作用,因为hasOne关系是关键。它应该只接收一行。代码证明了这一点:我使用的是
belongtomany
,我有
多对多
关系。当我有
多对多
关系时,我可以使用
hasOne
吗?你能想象你的回答给我的结果和我描述的一样吗?为什么?我现在不明白。当我在单个实体上调用
lastRole()
时,它工作正常,但在组查询中,当我想使用
with()
检索
all()
时,它在全局上下文中施加了
限制
,这是一个遗憾。。。
public function latestRole()
{
 return $this->hasOne(Role::class)->withPivot('timestamp')->orderBy('timestamp', 'DESC');
}
$this->with('latestRole')->get();