Laravel:对Eloquent过滤器的查询字符串


Laravel: Query string to Eloquent filter

我需要一个小函数,将查询字符串并将其转换为3个查询之一:

    WHERE column BETWEEN value AND value
  • WHERE column = value
  • WHERE column in (value, value,…)

我现在正在做的是:

// USE: ?price[between][min]=0&price[between][max]=100&size[in][value]=L&size[in][value]=M
$filters = ['price', 'size'];
$products= Product::query();
foreach($filters as $filter)
{
    if(isset($input[$filter]) && array_filter($input[$filter][key($input[$filter])]))
    {
        sort($input[$filter][key($input[$filter])]);
        $products->{'where' . ucfirst(key($input[$filter]))}($filter, $input[$filter][key($input[$filter])]);
    }
}
return $products->get();

以下是我的问题:

  1. 这是一个好方法吗?如果是这样,那么这种逻辑在哪里适用呢?
  2. 是否已经有一个包来处理这个逻辑?
  3. 如果以上都不是,那么实现这一目标的最佳方法是什么?
    我会简化事情。至于位置,我会把它放在productrerepository中(如果您使用Repository Pattern)。如果你没有,我会把它放在一个函数在模型。我不知道。没有看到任何东西,但我不是在寻找这样的东西。个人认为,最好的方法是在存储库中创建一个函数,简化查询字符串和代码。

这个查询字符串可能会有一些问题,因为var_dump会导致如下结果:

array(2) {
    'price' =>
    array(1) {
        'between' =>
        array(2) {
            'min' => string(1) "0"
            'max' => string(3) "100"
        }
    }
    'size' =>
    array(1) {
        'in' =>
        array(1) {
            'value' => string(1) "M"
        }
    }
}

您可以看到变量size的值L丢失了,因为它被M取代了。当然,您可以添加另一个数组,但如果您可以简化为这样的内容:

?price[between]=0,100&size[in]=L,M

无论如何,出于可读性的考虑,我更喜欢下面的代码。

$qString = Input::all();
$model = App::make('Product');
$products = $model->where(function($query) use($qString) {
    foreach($qString as $column => $operations) {
        foreach($operations as $operator => $values) {
            switch($operator) {
                case 'between': 
                    $query->whereBetween($column, array($values['min'], $values['max']));
                    break;
                case 'in': 
                    $query->whereIn($column, $values);
                    break;
            }
            // or replace the switch with this:
            // $query->{'where' . ucfirst($operator)}($column, $values);
        }
    }
})->get(); 

请注意,这还没有经过测试(尽管我在我的Repository方法中使用了闭包并且它们可以工作),您可能需要稍微调整一下。

还要注意,如果您像我建议的那样选择查询字符串,您可能需要一些验证。