使用Laravel 5.4
我正在伸出手来,因为我很难绕过这个问题并且在互联网上搜索了一整天(和stackoverflow)之后我找不到解决我的问题的好方法。
基本上,我有一个用户对象,它查询子对象,而子对象又包含一个子对象,我需要在该孙对象上使用where
进行过滤。
看起来像这样:
User =>
Pet(1) =>
PetServiceItem <= ServiceItem(1)
PetServiceItem <= ServiceItem(2)
PetServiceItem <= ServiceItem(3)
Pet(2) =>
PetServiceItem <= ServiceItem(1)
PetServiceItem <= ServiceItem(4)
PetServiceItem <= ServiceItem(5)
我会发布信息的相关部分,以便有人可以告诉我如何做到这一点。
用户模型
class User extends Authenticatable
{
public function pets()
{
return $this->hasMany(Pet::class);
}
}
宠物模型
class Pet extends Model
{
protected $fillable = [
'id',
'user_id',
...];
public function user()
{
return $this->belongsTo(User::class);
}
public function petServiceItems(){
return $this->hasMany(PetServiceItem::class);
}
}
PetServiceItem模型
class PetServiceItem extends Model
{
protected $fillable = [
'pet_id',
'service_item_id',
'approved'
];
protected $table = 'pet_service_item';
public function pet()
{
return $this->belongsTo(Pet::class);
}
public function serviceItem()
{
return $this->belongsTo(ServiceItem::class);
}
}
ServiceItem模型
class ServiceItem extends Model
{
protected $fillable = [
'id',
...,
'start_date',
'end_date',
'...',
];
public function pets(){
return $this->hasMany(PetServiceItem::class);
}
}
使用 Tinker 我可以执行以下操作:
$user->pets()->with(['petServiceItems', 'petServiceItems.service'])->get()
获取此数据:
=> Illuminate\Database\Eloquent\Collection {#1118
all: [
App\Pet {#1120
id: 1,
user_id: 6,
name: "Coco",
slug: "carol!coco",
image: "/dist/images/pets/carol/coco.jpg",
breed: null,
color: null,
gender: "Female",
birthdate: "2013-07-06 03:58:46",
fixed: 0,
weight: "48",
licensed: "",
tattoo: "",
microchip: "",
created_at: "2017-07-17 17:37:54",
updated_at: "2017-07-17 17:37:54",
petServiceItems: Illuminate\Database\Eloquent\Collection {#1126
all: [
App\PetServiceItem {#1132
id: 1,
provider_id: 2,
pet_id: 1,
service_item_id: 1,
approved: 1,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
serviceItem: App\ServiceItem {#1137
id: 1,
provider_id: 2,
type: "WALK",
subtype: "",
title: "7am 30min Walk between 7am and 10am",
desc: "Daily weekday walks between 7am and 10am",
day1: 0,
day2: 1,
day3: 1,
day4: 1,
day5: 1,
day6: 1,
day7: 0,
needs_approval: 0,
start_date: "2017-07-17 00:00:00",
end_date: "2017-10-17 00:00:00",
all_day: 0,
start_time: "07:00:00",
end_time: "10:00:00",
duration: 30,
pricing_one: 2000,
pricing_twoplus: 1800,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
deleted_at: null,
},
},
App\PetServiceItem {#1134
id: 3,
provider_id: 2,
pet_id: 1,
service_item_id: 4,
approved: 0,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
serviceItem: App\ServiceItem {#1139
id: 4,
provider_id: 2,
type: "AGILITY",
subtype: "",
title: "10am Agility Tu/Th",
desc: "Agility class @ 10am Tuesdays and Thursdays for 90 minutes",
day1: 0,
day2: 0,
day3: 1,
day4: 0,
day5: 1,
day6: 0,
day7: 0,
needs_approval: 1,
start_date: "2017-07-17 00:00:00",
end_date: "2017-09-17 00:00:00",
all_day: 0,
start_time: "10:00:00",
end_time: "11:30:00",
duration: 90,
pricing_one: 5000,
pricing_twoplus: 4500,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
deleted_at: null,
},
},
],
},
},
App\Pet {#1123
id: 2,
user_id: 6,
name: "Ruby",
slug: "carol!ruby",
image: "/dist/images/pets/carol/ruby.jpg",
breed: null,
color: null,
gender: "Female",
birthdate: "2012-06-16 22:47:43",
fixed: 1,
weight: "53",
licensed: "",
tattoo: "",
microchip: "",
created_at: "2017-07-17 17:37:54",
updated_at: "2017-07-17 17:37:54",
petServiceItems: Illuminate\Database\Eloquent\Collection {#1119
all: [
App\PetServiceItem {#1133
id: 2,
provider_id: 2,
pet_id: 2,
service_item_id: 1,
approved: 1,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
serviceItem: App\ServiceItem {#1137},
},
App\PetServiceItem {#1135
id: 4,
provider_id: 2,
pet_id: 2,
service_item_id: 4,
approved: 0,
created_at: "2017-07-17 17:37:57",
updated_at: "2017-07-17 17:37:57",
serviceItem: App\ServiceItem {#1139},
},
],
},
},
],
}
现在我需要在 start_date 的ServiceItem上执行 where 子句。
我试过了:
$user->pets()->with(['petServiceItems', 'petServiceItems.serviceItem'])->where('service_items.start_date', '>=', '2017-01-01')->get()
但是,我收到了这个错误:
使用消息&#39; SQLSTATE [42S22]照亮\ Database \ QueryException: 未找到列:1054未知列&#39; service_items.start_date&#39;在 &#39; where where&#39; (SQL:select {from
pets
其中pets
。user_id
= 6 和pets
。user_id
不为空且service_items
。start_date
&gt; = 2017年1月1日)&#39;
如何使用 where 子句(或其他需要的东西)来过滤我需要的数据?
编辑: 我已经发现这是我想要的SQL(或接近足够的近似值):
select * from users
join (select * from pets) pet on users.id = pet.user_id
join (select * from pet_service_item) psi on psi.pet_id = pet.id
join (select * from service_items) si on si.id = psi.service_item_id
join (select * from providers) prov on prov.id = si.provider_id
where si.start_date >= '2017-07-17'
AND si.end_date <= '2017-10-18'
AND prov.id = 2
AND users.id = 6
答案 0 :(得分:0)
Where子句使用表的名称而不是模型。试试这个:
$user->pets()->with(['petServiceItems', 'petServiceItems.serviceItem'])
->where('service_items.start_date', '>=', '2017-01-01')->get();
答案 1 :(得分:0)
所以,我发布这个,因为我从来没有真正得到答案,我最终得到了一个解决方案,但不完全是我正在寻找的解决方案。
如果有人有兴趣,最后,我就是这样做的(请注意:这会使数据变得平坦,无论出于什么意图和目的,在我的场景中都能正常工作)。
$services = App\ServiceItem::where('provider_id', '=', $provider->id)
->where('user.user_id', '=', $user->id)
->where('start_date', '<=', $end_date)
->where('end_date', '>=', $start_date)
->orWhereNull('end_date')
->where('pet.pet_user_id', '=', $user->id)
->whereNull('service_items.deleted_at')
->whereNUll('pet.pet_deleted_at')
->join(DB::raw('(select pet_id as psi_pet_id, service_item_id as psi_service_item_id from pet_service_items) psi'), function($join) {
$join->on('psi.psi_service_item_id', '=', 'service_items.id');
})
->join(DB::raw('(select id as pet_id, user_id as pet_user_id, name as pet_name, deleted_at as pet_deleted_at from pets) pet'), function($join) {
$join->on('pet.pet_id', '=', 'psi.psi_pet_id');
})
->join(DB::raw('(select id as user_id, name as user_name, deleted_at as user_deleted_at from users) user'), function($join) {
$join->on('user.user_id', '=', 'pet.pet_user_id');
});
return ['status' => 200, 'services' => $services->get()];