我有以下表格(以及相关字段):
users (id, name)
companies (id, name)
sales (id, company_id, user_id)
products (id, description)
products_sales (id, product_id, sale_id)
现在,我有一些带有多个并发过滤器的报告生成: 公司名称,用户名,产品。
我希望公司成为最高级别的公司。结果中的对象。 所以,
Company::where('name', 'LIKE', "%$company_name%")
然后
->whereHas('sales', function ($query) use ($user_name) {
$query->whereHas('user', function ($query2) use ($user_name) {
$query2->where('name', 'LIKE', "%$user_name%")
});
});
这已经足够复杂了,我也希望加载所有 关系,以优化数据库访问,所以我最终得到:
$cond = function($q) use ($user_name) {
$cond2 = function ($q2) use ($user_name) {
$q2->where('name', 'LIKE', "%$user_name%");
};
$q->whereHas('user', $cond2)
->with(['user' => $cond2]);
};
Company::where('name', 'LIKE', "%$company_name%")
->whereHas('sales', $cond)
->with(['sales' => $cond]);
我觉得这会带来不必要的重复。而且,过滤时 产品以同样的方式,我认为急切的加载取代了前一个产品。
那么......有什么更好的方法呢? 我可以使用Eloquent吗?或者我应该回到原始的'查询?
答案 0 :(得分:1)
您可以使用getQueryLog
检查Eloquent生成的查询。如果您的查询看起来不是最佳",您可能会考虑原始查询。
如果您的查询是最佳的,但Eloquent语法看起来太乱了"凌乱",您可以考虑在模型中构建部分query scopes。
例如,您可以在Sales
模型中定义范围以匹配名称:
class Sales extends Model
{
/**
* Scope a query to only include Sales for users with a matching name.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeMatchUserName($query, $user_name)
{
$cond2 = function ($q2) use ($user_name) {
$q2->where('name', 'LIKE', "%$user_name%");
};
return $query->with(['user' => $cond2])
->whereHas('user', $cond2);
}
}
然后你的查询变得更简单(看起来):
$cond = function($q) use ($user_name) {
return $q->matchUserName($user_name);
};
Company::where('name', 'LIKE', "%$company_name%")
->with(['sales' => $cond])
->whereHas('sales', $cond);
您甚至可以将该查询打包到您的Company
模型中:
class Company extends Model
{
/**
* Scope a query to only include Companies and Sales for a matching user and company name.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeMatchCompanyAndUserName($query, $user_name, $company_name)
{
$cond = function($q) use ($user_name) {
return $q->matchUserName($user_name);
};
return $query->where('name', 'LIKE', "%$company_name%")
->with(['sales' => $cond])
->whereHas('sales', $cond);
}
}
然后您需要做的就是:
Company::matchCompanyAndUserName($user_name, $company_name);