Php Laravel查询具有急切加载条件的多对多记录
所以我的应用程序有这样的结构Php Laravel查询具有急切加载条件的多对多记录,php,sql,laravel,eloquent,Php,Sql,Laravel,Eloquent,所以我的应用程序有这样的结构 付款有多个付款人 付款人属于用户(用户有许多付款人) 我想查询特定用户ID的所有付款(和透视数据)。我一直在使用此查询返回所有付款,而不管用户ID: $payment_data = Payment::with('payers')->get(); 现在,如果我只想获得付款人的用户id为(比如)5的付款,我尝试了以下方法: $payment_data = Payment::with(array( 'payers' => function
- 付款有多个付款人
- 付款人属于用户(用户有许多付款人)
$payment_data = Payment::with('payers')->get();
现在,如果我只想获得付款人的用户id为(比如)5的付款,我尝试了以下方法:
$payment_data = Payment::with(array(
'payers' => function($q){
$q->where('user_id', '=', 5);
}))->get();
但它返回几乎相同的结果,除了条件仅适用于付款人,而不适用于付款,即如果未满足用户id
条件,我仍然获得付款表中的所有付款,只是不适用于透视数据。从技术上讲,我可以只使用这个结果,过滤掉付款人
子数组为空的结果,但如果支付量很大,这将变得非常低效
形成此查询的正确方式是什么
编辑
以下是我的数据库结构的基本表示:
简单的SQL查询应该是这样的(RDMS各不相同,但您可以理解):
使用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(不存在),它仍然返回所有付款,并且每个付款方的数组都是空的,而实际上它应该返回一个完全空的结果
为即时加载生成的两个查询是:
select * from "payments" --I want to add my user_id condition to this
及
使用的方法仅用于加载关系,该关系上的约束应设置为:
$payment_data = Payment::whereHas('payers', function($q){
$q->where('payers.user_id', '=', 5);
})->get();
);
还可以指定要在where子句中使用的变量:
试着用另一种方法来做
User::find(5)->with('payers.payments')->get();
您将拥有一个包含付款人及其付款的类,以便获得循环付款人所需的所有信息,我认为joins可以完美地完成这项工作,因为您不需要循环。好的,经过广泛搜索,a我得到了答案:
您首先需要使用whereHas
,仅为所需用户获得付款:
$payments = Payment::whereHas('payers', function($q){
$q->where('user_id', '=', Auth::user()->id);
},'>=', DB::raw('1'))->get();
然后,您不需要在整个支付
模型上调用即时加载,而只需在您刚刚进行的支付收款上调用它(延迟即时加载):
这会将pivot数据添加到$payments集合中,为您提供所需的信息,而无需查询数据库中的每一笔付款(这是问题中的第一个方法所做的)。我认为这不正确,因为这只是添加了一个子查询,用于确定布尔结果(如果我们可以找到一些用户ID为5的付款人,请返回所有付款). 查询应该连接表并添加条件。上面添加了更多详细信息。在发布之前,我使用类似的模型测试了查询,它只返回带有付款人条件的付款。我在模型上测试了查询,结果为空。请参见上面的编辑关于此内容:Payment::with('payers')->join('payers','Payment.id','=','payers.id')->其中('payers.user_id','=',5)->get(),确定我检查了编辑问题,至少你会知道如何在相关模型中使用join子句来调整它以适应你的模型。这似乎是在做某种无限循环操作,但最后忘了添加get()方法。
$payment_data = Payment::whereHas('payers', function($q) use ($foo){
$q->where('payers.user_id', '=', $foo);
})->get();
);
User::find(5)->with('payers.payments')->get();
$payments = Payment::whereHas('payers', function($q){
$q->where('user_id', '=', Auth::user()->id);
},'>=', DB::raw('1'))->get();
$payment_data = $payments->load(array(
'payers' => function($q){
$q->where('user_id', '=', Auth::user()->id);
}));