【发布时间】:2014-03-10 11:16:22
【问题描述】:
所以我的应用具有这样的结构。
- payments hasAndBelongsToMany payers
- payers属于users(users有Many payers)
我想查询某个用户 ID 的所有付款(和数据透视数据)。我一直在使用这个返回所有付款的查询,无论 user_id 是什么:
$payment_data = Payment::with('payers')->get();
现在,如果我只想获得付款人的 user_id 为 5 的付款,我尝试了以下操作:
$payment_data = Payment::with(array(
'payers' => function($q){
$q->where('user_id', '=', 5);
}))->get();
但它返回几乎相同的结果,除了条件仅适用于付款人,而不是付款,即我仍然在付款表中获得所有付款,如果user_id 则不是数据透视数据条件不满足。从技术上讲,我可以只使用此结果并过滤掉 payers 子数组为空的结果,但如果有大量付款,这将变得非常低效。
形成这个查询的正确方法是什么?
编辑
这是我的数据库结构的基本表示:
简单的 SQL 查询将是这样的(RDMS 有所不同,但你明白了):
SELECT payments.*, payers_payments.*
FROM payments
RIGHT JOIN (payers
LEFT JOIN payers_payments
ON payers.id = payers_payments.payer_id)
ON payments.id = payers_payments.payment_id
WHERE payers.user_id = 5;
使用wherehas 会得到以下结果:
SELECT *
FROM "payments"
WHERE (SELECT Count(*)
FROM "payers"
INNER JOIN "payer_payment"
ON "payers"."id" = "payer_payment"."payer_id"
WHERE "payer_payment"."payment_id" = "payments"."id"
AND "payers"."user_id" = '1') >= '1'
这不是我想要的。
编辑 2
好的,经过一番折腾,我知道我需要使用即时加载,因为我需要数据透视字段以及支付模型本身的字段。这是一个显示 3 笔付款及其数据透视表的示例:
Array
(
[0] => Array
(
[id] => 2
[payment_date] => 2014-03-07
[company] => Franco Manca
[item] => Pizza
[created_at] => 2014-03-10 10:16:08
[updated_at] => 2014-03-10 10:16:08
[payers] => Array
(
[0] => Array
(
[id] => 1
[name] => tim
[email] => tim@tim.com
[user_id] => 1
[created_at] => 2014-03-10 10:07:23
[updated_at] => 2014-03-10 10:07:23
[pivot] => Array
(
[payment_id] => 2
[payer_id] => 1
[amount] => 21.0
[pays] => 0
[created_at] => 2014-03-10 10:16:08
[updated_at] => 2014-03-10 10:27:45
)
)
[1] => Array
(
[id] => 2
[name] => tom
[email] => tom@tom.com
[user_id] => 1
[created_at] => 2014-03-10 10:16:35
[updated_at] => 2014-03-10 10:16:35
[pivot] => Array
(
[payment_id] => 2
[payer_id] => 2
[amount] => 0.0
[pays] => 1
[created_at] => 2014-03-10 10:27:45
[updated_at] => 2014-03-10 10:27:45
)
)
)
)
[1] => Array
(
[id] => 3
[payment_date] => 2014-03-05
[company] => Kaff
[item] => Cocktail
[created_at] => 2014-03-10 10:17:05
[updated_at] => 2014-03-10 10:17:05
[payers] => Array
(
[0] => Array
(
[id] => 1
[name] => tim
[email] => tim@tim.com
[user_id] => 1
[created_at] => 2014-03-10 10:07:23
[updated_at] => 2014-03-10 10:07:23
[pivot] => Array
(
[payment_id] => 3
[payer_id] => 1
[amount] => 12.0
[pays] => 1
[created_at] => 2014-03-10 10:17:05
[updated_at] => 2014-03-10 10:17:05
)
)
[1] => Array
(
[id] => 2
[name] => tom
[email] => tom@tom.com
[user_id] => 1
[created_at] => 2014-03-10 10:16:35
[updated_at] => 2014-03-10 10:16:35
[pivot] => Array
(
[payment_id] => 3
[payer_id] => 2
[amount] => 19.0
[pays] => 1
[created_at] => 2014-03-10 10:17:05
[updated_at] => 2014-03-10 10:17:05
)
)
)
)
)
问题是,如果我随后将 user_id 条件更改为 99999(它不存在),它仍然返回所有付款,其中 payers 数组为每个为空,而实际上它应该返回一个完全空的结果。
为预先加载生成的 2 个查询是:
select * from "payments" --I want to add my user_id condition to this
和
SELECT "payers".*,
"payer_payment"."payment_id" AS "pivot_payment_id",
"payer_payment"."payer_id" AS "pivot_payer_id",
"payer_payment"."amount" AS "pivot_amount",
"payer_payment"."pays" AS "pivot_pays",
"payer_payment"."created_at" AS "pivot_created_at",
"payer_payment"."updated_at" AS "pivot_updated_at"
FROM "payers"
INNER JOIN "payer_payment"
ON "payers"."id" = "payer_payment"."payer_id"
WHERE "payer_payment"."payment_id" IN ( '2', '3' )
AND "user_id" = '1' --This satisfies the condition
【问题讨论】: