如何在laravel中的嵌套关系上放置where条件?
Posted
技术标签:
【中文标题】如何在laravel中的嵌套关系上放置where条件?【英文标题】:How to put where condition on nested relation in laravel? 【发布时间】:2021-08-24 06:23:35 【问题描述】:我有一张与consignment
hasMany
有关系的发票
public function consignments_invoices()
return $this->hasMany('App\Models\Admin\Consignment', 'invoice_id');
并且寄售与hasMany
有关系Charge
public function charges()
return $this->hasMany('App\Models\Admin\Charge', 'object_id')->where('model', 'Consignment');
在charge
这里我想把where子句放在属性rate_zone_id
上
我怎样才能做到这一点?
我有类似的现有查询
Invoice
::when(!empty($request->customer_id), function ($q) use ($request)
return $q->where('customer_id', $request->customer_id);
)
->where('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date)
->with('consignments_invoices')->
->when(!empty($request->rate_zone_id), function ($q) use ($request)
//Here is want to use where condition on rate zone id
)
->get();
【问题讨论】:
【参考方案1】:为此,您可以使用whereHas()。 whereHas()
可以使用点表示法 (consignments_invoices.charges
) 进行嵌套关系,因此您会得到如下内容:
$query->whereHas('consignments_invoices.charges', function ($query) use ($request)
$query->where('rate_zone_id', $request->rate_zone_id);
);
此外,when() 将第一个参数作为第二个参数传递给回调,因此您可以有类似的内容:
->when($request->rate_zone_id, function ($q, $rateZoneId)
$q->whereHas('consignments_invoices.charges', function ($q) use ($rateZoneId)
$q->where('rate_zone_id', $rateZoneId);
);
)
这意味着整个查询看起来像:
Invoice
::when($request->customer_id, function ($q, $customerId)
return $q->where('customer_id', $customerId);
)
->when($request->rate_zone_id, function ($q, $rateZoneId)
$q->whereHas('consignments_invoices.charges', function ($q) use ($rateZoneId)
$q->where('rate_zone_id', $rateZoneId);
);
)
->where('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date)
->get();
以上内容会将发票限制为特定的rate_zone_id
(提供时),但不会限制consignments_invoices
。
为此,您还需要在 with()
调用中约束 consignments_invoices
关系:
->with([
'consignments_invoices' => function ($query) use ($request)
$query->with('charges')->when($request->rate_zone_id, function ($q, $rateZoneId)
$q->whereHas('charges', function ($q) use ($rateZoneId)
$q->where('rate_zone_id', $rateZoneId);
);
);
,
])
这意味着您的整个查询将如下所示:
Invoice
::with([
'consignments_invoices' => function ($query) use ($request)
$query->with('charges')->when($request->rate_zone_id, function ($q, $rateZoneId)
$q->whereHas('charges', function ($q) use ($rateZoneId)
$q->where('rate_zone_id', $rateZoneId);
);
);
,
])
->when($request->customer_id, function ($q, $customerId)
return $q->where('customer_id', $customerId);
)
->when($request->rate_zone_id, function ($q, $rateZoneId)
$q->whereHas('consignments_invoices.charges', function ($q) use ($rateZoneId)
$q->where('rate_zone_id', $rateZoneId);
);
)
->where('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date)
->get()
【讨论】:
它可以工作,但它也在获取那些没有 rate_zone_id 的货物 如果一个托运的费用具有正确的 rate_zone_id,它正在获取所有托运 @BilalArshad 您在哪里/如何装载货物?我在你原来的问题中没有看到这一点。 @BilalArshad 您是否也要承担费用? @BilalArshad 这回答了你的问题吗?如果是这样,请您将其标记为已接受:)【参考方案2】:你可以使用嵌套关系
Invoice::when(!empty($request->customer_id), function ($q) use ($request)
return $q->where('customer_id', $request->customer_id);
)->where('start_date', '>=', $request->start_date)->whereDate('end_date', '<=', $request->end_date)
->when(!empty($request->rate_zone_id), function ($q) use ($request)
$q->whereHas('consignments_invoices.charges',function ($query) use ($request)
$query->where('rate_zone_id',$request->rate_zone_id);
);
)->get();
【讨论】:
如果一个托运的费用具有正确的 rate_zone_id 它正在获取其所有托运 Invoice::when(!empty($request->customer_id), function ($q) use ($request) return $q->where('customer_id', $request->customer_id ); )->where('start_date', '>=', $request->start_date)->whereDate('end_date', 'end_date) ->whereHas('consignments_invoices') ->when(!empty($request->rate_zone_id), function ($q) use ($request) $q->whereHas('consignments_invoices.charges',function ($query) use ($request) $query ->where('rate_zone_id',$request->rate_zone_id); ); )->get();【参考方案3】:$invoice = Invoice::with('charges')
->when(!empty($request->customer_id), function ($q) use ($request)
return $q->where('customer_id', $request->customer_id);
)
->whereDate('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date);
if (!empty($request->rate_zone_id))
$invoice->whereHas('charges', function ($query1)use($request)
$query1->where('rate_zone_id', $request->rate_zone_id);
);
$invoices = $invoice->get()->toArray();
或者
$invoices = Invoice::with('charges')
->when(!empty($request->customer_id), function ($q) use ($request)
return $q->where('customer_id', $request->customer_id);
)
->whereDate('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date)
->when(!empty($request->rate_zone_id), function ($query1) use ($request)
$rate_zone_id = $request->rate_zone_id;
$query1->whereHas('charges', function ($query2)use($rate_zone_id)
$query2->where('rate_zone_id', $rate_zone_id );
);
)->get()->toArray();
$invoice = Invoice::when(!empty($request->customer_id), function ($q) use ($request)
return $q->where('customer_id', $request->customer_id);
)
->whereDate('start_date', '>=', $request->start_date)
->whereDate('end_date', '<=', $request->end_date);
if (!empty($request->rate_zone_id))
$rate_zone_id = $request->rate_zone_id;
$invoice->with(['charges', function ($query1)use($rate_zone_id)
$query1->where('rate_zone_id', $rate_zone_id);
]);
$invoices = $invoice->get()->toArray();
使用 whereHas=> https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence
【讨论】:
如果一个托运的费用具有正确的 rate_zone_id 它正在获取其所有托运 好的,那么在这种情况下,还可以通过急切加载添加条件 $invoice = Invoice::when(!empty($request->customer_id), function ($q) use ($request) return $q->where('customer_id', $request ->customer_id); ) ->whereDate('start_date', '>=', $request->start_date) ->whereDate('end_date', 'end_date); if (!empty($request->rate_zone_id)) $invoice->with('charges', function ($query1)use($request) $query1->where('rate_zone_id', $request->rate_zone_id) ; ); $invoices = $invoice->get()->toArray(); 还是一样的结果 rate_zone_id 单个还是多个?以上是关于如何在laravel中的嵌套关系上放置where条件?的主要内容,如果未能解决你的问题,请参考以下文章