Php Laravel雄辩的查询意外的结果
我发现一些查询结果确实出乎意料 它是拉威尔5.2 我们有以下实体: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),因为我们保存着关于时间的信息,当用户达到特定角色时 我
用户
方法:
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();