Laravel — расширение предложений Eloquent where в зависимости от динамических параметров

Я хотел бы создать серию красноречивых предложений WHERE, зависящих от параметров поиска, которые я собираю из объекта json.

Примерно так (не берите в голову синтаксис объекта ,,, это интерпретация только для демонстрации):

$searchmap = "{
"color": "red",
"height": "1",
"width": "2",
"weight": "",
"size": "",
}";

Затем я беру объект и декодирую, чтобы получить массив поиска …

$search = json_decode($searchmap, true);

Если бы мой вес и размер были равны нулю или были бы «пустой строкой», у меня был бы красноречивый код, который выглядит следующим образом.

$gadgets = Gadget::where('color',   '=', $search['color'])
->where('height',  '=', $search['height'])
->where('width',   '=', $search['width'])
->paginate(9);

Если они имеют значение, то красноречивый код будет выглядеть так:

$gadgets = Gadget::where('color',   '=', $search['color'])
->where('height',  '=', $search['height'])
->where('width',   '=', $search['width'])
->where('weight',  '=', $search['weight'])
->where('size',    '=', $search['size'])
->paginate(9);

Есть ли способ сделать это динамически.

Я полагаю, что вопрос должен заключаться в том, чтобы найти способ цепочки красноречивых, где предложения динамически основаны на заданном параметре?

В псевдо-контексте я хочу сделать что-то вроде этого

$gadgets = Gadget::

foreach ($search as $key => $parameter) {
if ( $parameter <> '' ) {
->where($key, '=', $parameter)
}
}

->paginate(9);

Можно ли создать цепочку предложений where в некотором роде, похожем на это?

Спасибо, что нашли время посмотреть на это!


ОБНОВИТЬ:

Я также придумал что-то вроде этого, которое, кажется, работает хорошо, но я хотел бы приветствовать предложения, если улучшение является хорошей идеей.

$gadgets = New Gadget();
foreach ($search as $key => $parameter) {
if($parameter != ''){
$gadgets = $gadgets->where($key, '=', $parameter);
}
}
$gadgets = $gadgets->paginate(9);

ЗАВЕРШЕНИЕ

И благодаря @lukasgeiter ниже я думаю, что пойду с этим

$gadgets = Gadget::whereNested(function($query) use ($search) {
foreach ($search as $key => $value)
{
if($value != ''){
$query->where($key, '=', $value);
}
}
}, 'and');
$gadgets = $gadgets->paginate(9);

3

Решение

Это легко. Laravel-х where Функция позволяет передавать массив пар ключ-значение.

$searchmap = array(
'color' => 'red',
'height' => '1'
// etc
);

$gadgets = Gadget::where($searchmap)->paginate(9);

Если вам интересно, это соответствующая часть источника (\Illuminate\Database\Query\Builder)

public function where($column, $operator = null, $value = null, $boolean = 'and')
{
// If the column is an array, we will assume it is an array of key-value pairs
// and can add them each as a where clause. We will maintain the boolean we
// received when the method was called and pass it into the nested where.
if (is_array($column))
{
return $this->whereNested(function($query) use ($column)
{
foreach ($column as $key => $value)
{
$query->where($key, '=', $value);
}
}, $boolean);
}

// many more lines of code....
}

редактировать

Чтобы иметь больше контроля над ним (например, изменив «=» на другой оператор сравнения), попробуйте использовать код, который Laravel использует для внутреннего использования:

$gadgets = Gadget::whereNested(function($query) use ($searchmap)
{
foreach ($searchmap as $key => $value)
{
if($value != ''){
$query->where($key, '=', $value);
}
}
}, 'and')->paginate(9);
7

Другие решения

Для тех, кому это нужно, вот модифицированная версия ответа lukasgeiter, которая решает проблему «переменного числа колес», а также позволяет (1) разные операторы для каждого where пункт и (2) способность также использовать whereIn когда один из ваших «Wheres» должен быть в состоянии соответствовать одному из нескольких значений (функция ниже обнаруживает, когда массив значений передается и, таким образом, использует whereIn вместо where).

$paramSets Присвоение переменной в начале (ниже) по существу описывает, как ее использовать.

$paramSets = [
"size"=>["op"=>"=","values"=>"large"],
"production_date"=>["op"=>">=","values"=>"2015-12-31"],
"color"=>["op"=>"=","values"=>["red","blue"]],
"name"=>["op"=>"like","values"=>"M%"]
];

$items = db::table('products')
->whereNested(function($query) use ($paramSets) {
foreach ($paramSets as $k => $v)
{
if ($v != ''){
if (is_array($v["values"])){
$query->whereIn($k,$v["values"]);
}
else {
$query->where($k, $v["op"], $v["values"]);
}
}
}
}, 'and');

dd($items->get());
1

По вопросам рекламы [email protected]