Laravel Eloquent Builder Расширенный Где - PullRequest
1 голос
/ 21 января 2020

У меня есть следующий интерфейс:

<?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%') })

В моей текущей реализации я не вижу очевидного способа достичь этого - кто-нибудь может направить меня в правильном направлении.

Спасибо.

1 Ответ

0 голосов
/ 21 января 2020

Вы не можете сделать это без использования условия, фильтры которого необходимо объединить в предложении where. Если я понял, вы должны использовать что-то вроде этого:

$unionFilters = []; // Need to wrap up below
foreach ($request->all() as $filterName => $search) {
    $filter = $this->instantiateFilter($filterName);

    if ($this->isValidFilter($filter) && $request->isMethod('get')) {
        switch ($filterName) {
            case 'tag':
            case 'title':
                $unionFilters[$filter::class] = $search;
                break;
            default:
                $query = $filter::apply($query, $search);
        }
    }
}

if (count($unionFilters)) {
    /** Wrap this filters */
    $query->where(function ($query) use ($unionFilters): void {
        foreach ($unionFilters as $filter => $search) {
            $query = $filter::apply($query, $search);
        }
    });

    unset($unionFilters);
}

return $query;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...