Laravel 5.4 Eloquent 从单个输入过滤
Laravel 5.4 Eloquent filter from a single input
我正在尝试使用 laravel eloquent 进行查询以加入带有地址和电话号码的公司 table 以便用户可以在单个输入字段中键入内容,例如地址行或数字,它将查询多个 tables/columns 且仅 return 个具有潜在匹配项。
我已经查看了 wherehas,但如果数字和地址 table 都匹配,它似乎会停止所有结果。
我相信在这些 table 上使用标准的左连接,我可以让它工作,但如果可能的话,我想要一个干净的解决方案。下面是我正在处理的内容,实际上 return 没有任何过滤结果,所以我有点摸不着头脑。
目标是单一输入以便于使用,但在多个 columns/tables 和 returning 行中搜索仅匹配。是否有 wherehas 选项但可能适用于多种情况?希望有人能理解我在做什么。
public function addresses(){
return $this->hasMany(Company_addresses::class, 'company_id', 'id');
}
public function digits(){
return $this->hasMany(Company_digit::class, 'company_id', 'id');
}
public static function search($request)
{
$filters = $request->all();
$sortby = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderby = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return static::with([
'addresses' => function ($query) use ($filters) {
$query->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
},
'digits' => function ($query) use ($filters) {
$query->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
}])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}
这就是您使用关系方法的方式。
您确实需要使用 ->whereHas()
,但您需要将 ->whereHas('addresses', ...)
和 ->orWhereHas('digits', ...)
都包装在 ->where(function ($q) ...)
方法中。
像这样:
public static function search($request)
{
$filters = $request->all();
$sortby = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderby = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return self::where(function ($q) use ($filters) {
$q->whereHas('addresses', function ($q) use ($filters) {
$q->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
})
->orWhereHas('digits', function ($q) use ($filters) {
$q->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
});
})
->with(['addresses', 'digits'])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}
虽然上面的代码应该有效,但我建议将搜索方法从 static
方法重写为 scope。我肯定会重写它以保持 $request
不在其中,因为请求与模型无关。
像这样:
// Use it like: \App\Company::search($request->all())->paginate(20);
public function scopeSearch($q, $filters)
{
$sortBy = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderBy = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return $q->where(function ($q) use ($filters) {
$q->whereHas('addresses', function ($q) use ($filters) {
$q->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
})
->orWhereHas('digits', function ($q) use ($filters) {
$q->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
});
})
->with(['addresses', 'digits'])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type']);
}
因为你在我还没能理解之前就得到了答案。这是我在澄清问题后 post 对代码进行的简单重构。
public static function search()
{
$name = request('name');
return static::whereHas('addresses', function ($query) use ($name) {
$query->where('address_line_1', "like", "%{$name}%")
->orWhere('address_line_2', "like", "%{$name}%")
->orWhere('city', "like", "%{$name}%")
->orWhere('county', "like", "%{$name}%")
->orWhere('post_code', "like", "%{$name}%");
})->orWhereHas('digits', function ($query) use ($name) {
$query->where('number', "like", "%{$name}%")
->orWhere('extension', "like", "%{$name}%");
})
->orderBy('companies.'.request('sortby', 'created_at'), request('orderby', 'desc'))
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}
我正在尝试使用 laravel eloquent 进行查询以加入带有地址和电话号码的公司 table 以便用户可以在单个输入字段中键入内容,例如地址行或数字,它将查询多个 tables/columns 且仅 return 个具有潜在匹配项。
我已经查看了 wherehas,但如果数字和地址 table 都匹配,它似乎会停止所有结果。 我相信在这些 table 上使用标准的左连接,我可以让它工作,但如果可能的话,我想要一个干净的解决方案。下面是我正在处理的内容,实际上 return 没有任何过滤结果,所以我有点摸不着头脑。
目标是单一输入以便于使用,但在多个 columns/tables 和 returning 行中搜索仅匹配。是否有 wherehas 选项但可能适用于多种情况?希望有人能理解我在做什么。
public function addresses(){
return $this->hasMany(Company_addresses::class, 'company_id', 'id');
}
public function digits(){
return $this->hasMany(Company_digit::class, 'company_id', 'id');
}
public static function search($request)
{
$filters = $request->all();
$sortby = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderby = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return static::with([
'addresses' => function ($query) use ($filters) {
$query->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
},
'digits' => function ($query) use ($filters) {
$query->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
}])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}
这就是您使用关系方法的方式。
您确实需要使用 ->whereHas()
,但您需要将 ->whereHas('addresses', ...)
和 ->orWhereHas('digits', ...)
都包装在 ->where(function ($q) ...)
方法中。
像这样:
public static function search($request)
{
$filters = $request->all();
$sortby = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderby = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return self::where(function ($q) use ($filters) {
$q->whereHas('addresses', function ($q) use ($filters) {
$q->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
})
->orWhereHas('digits', function ($q) use ($filters) {
$q->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
});
})
->with(['addresses', 'digits'])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}
虽然上面的代码应该有效,但我建议将搜索方法从 static
方法重写为 scope。我肯定会重写它以保持 $request
不在其中,因为请求与模型无关。
像这样:
// Use it like: \App\Company::search($request->all())->paginate(20);
public function scopeSearch($q, $filters)
{
$sortBy = isset($filters['sortby']) ? $filters['sortby'] : 'created_at';
$orderBy = isset($filters['orderby']) ? $filters['orderby'] : 'desc';
return $q->where(function ($q) use ($filters) {
$q->whereHas('addresses', function ($q) use ($filters) {
$q->where('address_line_1', "LIKE", '%'.$filters['name'].'%')
->orWhere('address_line_2', "LIKE", '%'.$filters['name'].'%')
->orWhere('city', "LIKE", '%'.$filters['name'].'%')
->orWhere('county', "LIKE", '%'.$filters['name'].'%')
->orWhere('post_code', "LIKE", '%'.$filters['name'].'%');
})
->orWhereHas('digits', function ($q) use ($filters) {
$q->where('number', "LIKE", '%'.$filters['name'].'%')
->orWhere('extension', "LIKE", '%'.$filters['name'].'%');
});
})
->with(['addresses', 'digits'])
->orderBy('companies.'.$sortby, $orderby)
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type']);
}
因为你在我还没能理解之前就得到了答案。这是我在澄清问题后 post 对代码进行的简单重构。
public static function search()
{
$name = request('name');
return static::whereHas('addresses', function ($query) use ($name) {
$query->where('address_line_1', "like", "%{$name}%")
->orWhere('address_line_2', "like", "%{$name}%")
->orWhere('city', "like", "%{$name}%")
->orWhere('county', "like", "%{$name}%")
->orWhere('post_code', "like", "%{$name}%");
})->orWhereHas('digits', function ($query) use ($name) {
$query->where('number', "like", "%{$name}%")
->orWhere('extension', "like", "%{$name}%");
})
->orderBy('companies.'.request('sortby', 'created_at'), request('orderby', 'desc'))
->select(['id', 'registered_name', 'trading_name', 'created_at', 'type'])
->paginate(20);
}