Laravel - 根据动态参数扩展 Eloquent where 子句

2021-12-26 00:00:00 php laravel laravel-4 eloquent

我想根据我从 json 对象收集的搜索参数构建一系列雄辩的 WHERE 子句.

I would like to construct a series of eloquent WHERE clauses dependent on the search parameters I collect from a json object.

像这样的东西(不管对象的语法,,,它是一种解释,只是为了演示):

Something like this (never mind the syntax of object,,, it is an interpretation only to demonstrate):

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

然后我取对象并解码以获得搜索数组...

I then take the object and decode to get a search array...

$search = json_decode($searchmap, true);

如果我的权重和大小设置为 null 或者是一个空字符串",我会有像这样的雄辩代码..

If my weight and size are set to null or are an 'empty string' I would have eloquent code that looks like this..

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

如果它们有一个值,那么雄辩的代码看起来像这样..

If they have a value then eloquent code would look like this..

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

有没有办法动态地实现这一点.

Is there a way to accomplish this dynamically.

我想问题应该在于有没有办法根据给定的参数动态链接雄辩的 where 子句?

I suppose the question should be ins there a way to chain eloquent where clauses dynamically based on a given parameter?

在伪上下文中,我希望做这样的事情

In a pseudo context I am looking to do something like this

$gadgets = Gadget::

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

->paginate(9);

是否可以以类似于此的方式创建 where 子句的链接?

Can chaining of where clauses be created in some way similar to this?

感谢您花时间看这个!

更新:

我也想出了类似这样的东西,似乎效果很好,但如果改进是个好主意,我欢迎提出建议.

I also came up with something like this that seems to work well but i would like to welcome suggestions if improvement is a good idea.

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

<小时>

最终版

感谢下面的@lukasgeiter,我想我会选择这个

And thanks to @lukasgeiter below I think I will go with this

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

推荐答案

这很简单.Laravel 的 where 函数允许你传入一个键值对数组.

That's easy. Laravel's where function allows you to pass in an array of key value pairs.

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

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

如果你好奇,那是源代码的相关部分 (IlluminateDatabaseQueryBuilder)

If you are curious, that's the relevant part of the source (IlluminateDatabaseQueryBuilder)

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 内部使用的代码:

Edit

To have more control over it (e.g. changing the "=" to another comparison operator) try using the code laravel uses internally directly:

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

相关文章