У меня есть следующий интерфейс:
<?php
namespace App\Filters\Contracts;
use Illuminate\Database\Eloquent\Builder;
interface FilterInterface
{
/**
* Apply a given search value to the builder instance.
*
* @param Builder $builder
* @param mixed $value
* @return Builder $builder
*/
public static function apply(Builder $builder, $value);
}
и следующие классы, которые реализуют вышеуказанный интерфейс:
<?php
namespace App\Filters;
use App\Filters\Contracts\FilterInterface;
use Illuminate\Database\Eloquent\Builder;
class Tag implements FilterInterface
{
/**
* Apply a given search value to the builder instance.
*
* @param Builder $builder
* @param mixed $value
* @return Builder $builder
*/
public static function apply(Builder $builder, $value)
{
return $builder->orWhere('tags', 'LIKE', '%' . $value . '%');
}
}
<?php
namespace App\SportsMediaGB\Filters;
use App\SportsMediaGB\Filters\Contracts\FilterInterface;
use Illuminate\Database\Eloquent\Builder;
class Title implements FilterInterface
{
/**
* Apply a given search value to the builder instance.
*
* @param Builder $builder
* @param mixed $value
* @return Builder $builder
*/
public static function apply(Builder $builder, $value)
{
return $builder->orWhere('title', 'LIKE', '%' . $value . '%');
}
}
<?php
namespace App\Filters;
use App\Filters\Contracts\FilterInterface;
use Illuminate\Database\Eloquent\Builder;
class Freeview implements FilterInterface
{
/**
* Apply a given search value to the builder instance.
*
* @param Builder $builder
* @param mixed $value
* @return Builder $builder
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('freeview', '=', (bool) $value);
}
}
Эти фильтры применяются на основе запросить запрос так:
<?php
namespace App\Filters\Traits;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
trait Filterable
{
public function applySearchCriteria(Request $request) {
$this->model = $this->parseSearchCriteriaFromRequest($request, $this->model->newQuery());
return $this;
}
protected function parseSearchCriteriaFromRequest(Request $request, Builder $query) {
foreach ($request->all() as $filterName => $search) {
$filter = $this->instantiateFilter($filterName);
if ($this->isValidFilter($filter) && $request->isMethod('get')) {
$query = $filter::apply($query, $search);
}
}
return $query;
}
protected function instantiateFilter($name) {
return 'App\Filters\\' . Str::studly($name);
}
protected function isValidFilter($filter) {
return class_exists($filter);
}
}
Моя проблема связана с фильтрами where
/ orWhere
. Если у меня есть следующая строка запроса:
?freeview=true&tag=test&title=test
, это выведет следующий запрос:
where('freeview', true)->orWhere('tag', 'LIKE', '%test%')->orWhere('title', 'LIKE', '%test%')
Я хотел бы вместо этого вывести следующее:
where('freeview', true)->where(function($query) {
$query->where('tag', 'LIKE', '%test%')->orWhere('title', 'LIKE', '%test%')
})
В моей текущей реализации я не вижу очевидного способа достичь этого - кто-нибудь может направить меня в правильном направлении.
Спасибо.