我正在使用laravel 5.5并且我有这个代码
$building = Building::findOrFail($building_id);
$units = $building->units()
->whereHas('parkingspaces',function($query) use($request){
$query->where('name','=', $request->search );
})
->orWhereHas('users',function($query) use($request){
$query->where('name','LIKE','%'.$request->search.'%');
})
->get();
我得到的结果是错误的,我希望它搜索建筑物的单位的用户/租户名称。但它也会进入其他建筑物并进行搜索。所以我在结果中让其他建筑物出现了单位。
我认为通过设置$ building,它会使所有查询更深入地搜索它。
$building->units()->with(['users','parkingspaces'])->get();
,获得正确的单位与用户和停车位连接到该单位。
关于我做错了什么的任何线索?
注意:Auth::user()->current_building()
从会话中获取建筑物的ID。
建立模型片段
class Building extends Model{
public function users()
{
return $this->belongsToMany('App\User','buildings_users');
}
public function tenants(){
return $this->belongsToMany('App\User','buildings_users')->whereHas('roles', function ($query) {
$query->where('name', '=', 'resident');
});
}
public function staff(){
return $this->belongsToMany('App\User','buildings_users')->whereHas('roles',function($query){
$query->where('name','!=','tenant')->where('name','!=','administrator')->where('name','!=','superadministrator');
});
}
public function managers(){
return $this->belongsToMany('App\User','buildings_users')->whereHas('roles',function($query){
$query->where('name','=','manager');
});
}
public function units(){
return $this->hasMany('App\Unit');
}
单位模型代码段
class Unit extends Model
{
//
public function building(){
return $this->belongsTo('App\Building');
}
public function users(){
return $this->belongsToMany('App\User','user_unit');
}
public function parkingspaces(){
return $this->hasMany('App\Parkingspace');
}
building_users
CREATE TABLE IF NOT EXISTS `buildings_users` (
`building_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
user_unit
CREATE TABLE IF NOT EXISTS `user_unit` (
`building_id` int(10) unsigned NOT NULL,
`unit_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
单位片段
CREATE TABLE IF NOT EXISTS `units` (
`id` int(10) unsigned NOT NULL,
`building_id` int(10) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
停车位
CREATE TABLE IF NOT EXISTS `parkingspaces` (
`id` int(10) unsigned NOT NULL,
`building_id` int(10) unsigned NOT NULL,
`unit_id` int(10) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
问题在于未经编组的orWhereHas()
电话。
您的$building->units()
关系构建一个SQL查询,如:
select * from units
where
units.building_id = ?
and units.building_id is not null
然后,您将关系的条件添加到此基本查询中,因此您的查询最终会像:
select * from units
where
units.building_id = ?
and units.building_id is not null
and exists([parkingspaces query])
or exists([users query])
最后一个or
条件是你获得额外记录的原因。即使所有三个第一个条件都是假的,如果最后一个条件匹配,也将返回记录(false AND false AND false OR true === true
)。
你需要做的是将你的条件分组,以便你的or
条件适当地限制(false AND false AND (false OR true) === false
)。你通过将一个闭包传递给where()
调用来做到这一点:
$units = $building->units()
->where(function ($query) use($request){
return $query
->whereHas('parkingspaces',function($query) use($request){
$query->where('name','=', $request->search );
})
->orWhereHas('users',function($query) use($request){
$query->where('name','LIKE','%'.$request->search.'%');
});
})
->get();
这将生成一个类似的查询:
select * from units
where
units.building_id = ?
and units.building_id is not null
and (
exists([parkingspaces query])
or exists([users query])
)
现在你的or
条件是适当的范围,你只会获得具有匹配id的建筑物的结果。
“has-many-through”关系提供了通过中间关系访问远程关系的便捷捷径。
// In your User model
public function units()
{
return $this->hasManyThrough(Unit::class, Building::class);
}
这样您就可以直接通过用户访问单元:
$units = Auth::user()->units;
Laravel不使用查询来访问用户的构建,然后再进行另一个查询来访问该构建的单元,而是使用带有连接的单个查询来获取成员。
hasManyThrough
关系Laravel docs:https://laravel.com/docs/5.3/eloquent-relationships#has-many-through