我正在尝试使用雄辩的查询生成器来获取laravel-scout tntsearch,事实证明这很困难,所以我目前的方法是首先使用tntsearch来获取结果,从结果中获取ID并从中获取带有摘除ID的wherIn子句,为此,我还有一个额外的QueryFilters类,以一种可组合的方式对其进行排序和过滤。
问题是我遇到以下错误:
Call to undefined method App\Filters\QueryFilters::merge()
这是我的代码:
public function search(Request $request, QueryFilters $filters)
{
//Search with tntsearch
$posts = Post::search($request->input('search'))->get();
//Grab ids and prepare to merge with $filters
$postIds = $posts->pluck('id');
$toMerge = collect(['whereIn' => $postIds]);
$filters->merge($toMerge);
//Filter and sort results
$posts = Post::filter($filters)->with(['postcategory','author','favorites'])->paginate(10);
}
QueryFilters的工作方式是遍历请求对象,以查找具有相同名称的方法,并在每次查询构建器实例时返回。
<?php
namespace App\Filters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
class QueryFilters
{
protected $request;
protected $builder;
public function __construct(Request $request)
{
$this->request = $request;
}
public function title($term)
{
$lowerCaseTerm = strtolower($term);
return $this->builder->where('title', 'LIKE', "%$lowerCaseTerm%");
}
public function postCategory($term)
{
if($term == 0)
{
return $this->builder->whereHas('postcategory', function ($query) use ($term){
$query->where('id', '>', 0);
});
}
return $this->builder->whereHas('postcategory', function ($query) use ($term){
$query->where('id', $term);
});
}
public function sortBy($term)
{
$sortArray = explode(",", $term);
for($i = 0; $i < count($sortArray); $i++)
{
$sortBy = substr_replace($sortArray[$i], "", -1);
$sortChar = substr($sortArray[$i], -1);
$sortOrder = $sortChar == '+' ? 'ASC' : 'DESC';
$this->builder->orderBy($sortBy, $sortOrder);
}
return $this->builder;
}
public function whereIn($postIds)
{
return $this->builder->whereIn('id', $postIds);
}
public function apply(Builder $builder)
{
$this->builder = $builder;
foreach ($this->filters() as $name => $value)
{
//if method doesn't exists continue out of the loop
if ( ! method_exists($this, $name))
{
continue;
}
//method exists so check if it has a value payload so call the method with arguments
if (strlen($value))
{
$this->$name($value);
}
//it doesn't have a payload so call the method without arguments
else
{
$this->$name();
}
}
return $this->builder;
}
public function filters()
{
//returns associative array of request body key value pairs
return $this->request->all();
}
}
要了解有关此类的更多信息,请参见这篇中等文章: https://medium.com/@mykeels/writing-clean-composable-eloquent-filters-edd242c82cc8
如果我dd $ filters我得到:
QueryFilters {#457
#request: Request {#43
#json: null
#convertedFiles: null
#userResolver: Closure($guard = null) {#421
class: "Illuminate\Auth\AuthServiceProvider"
this: AuthServiceProvider {#41 …}
use: {
$app: Application {#2 …}
}
file: "C:\xampp\htdocs\dog-media.es\vendor\laravel\framework\src\Illuminate\Auth\AuthServiceProvider.php"
line: "83 to 85"
}
#routeResolver: Closure() {#423
class: "Illuminate\Routing\Router"
this: Router {#26 …}
use: {
$route: Route {#220 …}
}
file: "C:\xampp\htdocs\dog-media.es\vendor\laravel\framework\src\Illuminate\Routing\Router.php"
line: "650 to 652"
}
+attributes: ParameterBag {#45
#parameters: []
}
+request: ParameterBag {#51
#parameters: array:3 [
"loaderId" => "1111"
"postCategory" => "0"
"sortBy" => "created_at+"
]
}
+query: ParameterBag {#51}
+server: ServerBag {#47
...
我的过滤范围:
<?php
namespace App\Filters;
use Illuminate\Database\Eloquent\Builder;
trait Filterable
{
public function scopeFilter($query, QueryFilters $filters)
{
return $filters->apply($query);
}
}