簡體   English   中英

Laravel - 根據動態參數擴展Eloquent子句

[英]Laravel - extending Eloquent where clauses depending on dynamic parameters

我想根據我從json對象收集的搜索參數構造一系列雄辯的WHERE子句。

像這樣的東西(不要介意對象的語法,,,它只是演示的解釋):

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

然后我拿對象並解碼得到一個搜索數組......

$search = json_decode($searchmap, true);

如果我的體重和大小設置為null或是一個“空字符串”,我會有一個看起來像這樣的雄辯代碼。

$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);

有沒有辦法動態完成這個。

我想這個問題應該是有一種方法可以根據給定的參數動態鏈接where子句嗎?

在偽上下文中,我希望做這樣的事情

$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);

這很容易。 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);

對於任何需要它的人來說,這里是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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM