Php Laravel高级搜索查询修复程序

Php Laravel高级搜索查询修复程序,php,laravel,laravel-5,eloquent,laravel-eloquent,Php,Laravel,Laravel 5,Eloquent,Laravel Eloquent,我有一个带有多个输入和选择框的搜索表单,我需要帮助来获取查询中的条件,以使每个部分都能同时单独工作 这是我的刀片代码: 最后,我的功能代码是: 选项模型: 子选项模型: 品牌模式: 笔记 我的品牌搜索来自products表,其中我有每个产品的brand_id列 但是 我的子选项来自名为product_suboption的第三个表,正如您在我的模型代码中看到的那样,我在其中保存product_id和suboption_id。这只是为了给出一个想法。您可以在查询中使用多个->where and ea

我有一个带有多个输入和选择框的搜索表单,我需要帮助来获取查询中的条件,以使每个部分都能同时单独工作

这是我的刀片代码:

最后,我的功能代码是:

选项模型:

子选项模型:

品牌模式:

笔记 我的品牌搜索来自products表,其中我有每个产品的brand_id列

但是


我的子选项来自名为product_suboption的第三个表,正如您在我的模型代码中看到的那样,我在其中保存product_id和suboption_id。

这只是为了给出一个想法。您可以在查询中使用多个->where and eager loading->with。 请看下面的查询:

$products = Product::where('price', '>=', $min_price) // you get the max and min price 
        ->where('id', '<=', $max_price)->select('id')
        ->with([
            "brand" => function ($query) {
                $query->whereIn('id', $brand_ids); // [1, 2, 3,...]
            },
            "specifications" => function ($query) {
                $query->where('some_column', '=', 'possible-value'); // single condition
            },
            "specifications.subspecifications" => function ($query) {
                $query->where([
                    'some_column' => 'possible-value',
                    'another_column' => 'possible-value'
                ]); // you can also pass arrays of condition
            }
        ])->get(); // This will return the products with the price set by the user
                   // Since we're just using ->with(), this will also return those products
                   // that doesn't match the other criteria specifications) so we 
                   // still need to filter it.
您可以使用laravel或Where和Where必须同时单独获得结果,假设您没有选择min_price和max_price,但是您选择了brand,那么所有带有此brnad的产品都应该返回,您的查询如下所示

$products = Product::orWhere('price','>=',$min_price)
->orWhere('price','<=',$max_price)
->orWhereHas('brand',function($query){
    $query->whereIn('id', $brand_ids);
})
->orWhereHas('suboptions',function($query){
    $query->whereIn('id', $suboptions_ids);
})
->orWhereHas('subspecifications',function($query){
    $query->whereIn('id', $subspecifications_ids);
})->get(); 
如果上述查询中所述的任何条件匹配,$products将有products集合


希望这能有所帮助。

以下是我的做法。请注意,使用when简化可选where条件也不需要设置变量,如果您希望急切地加载关系,则使用闭包约束whereHas和with

$products = Product::query()
    ->when($request->min_price, function ($query, $min_price) {
        return $query->where('price', '>=', $min_price);
    })
    ->when($request->max_price, function ($query, $max_price) {
        return $query->where('price', '<=', $max_price);
    })
    ->when($request->suboptions, function ($query, $suboptions) {
        $suboptionsConstraint = function ($q) use ($suboptions) {
            return $q->whereIn('id', $suboptions);
        };
        return $query->whereHas('suboptions', $suboptionsContraint)
            ->with(['suboptions' => $suboptionsContraint]);
    })
    ->when($request->brands, function ($query, $brands) {
        $brandsConstraint = function ($q) use ($brands) {
            return $q->whereIn('id', $brands);
        };
        return $query->whereHas('brands', $brandsConstraint)
            ->with(['brands' => $brandsConstraint]);
    });

我建议采用不同的方法

在控制器上,将其更改为:

public function advancedsearch(Request $request) {

$suboptions2 = request->suboptions ? request->suboptions : null;
$min_price = request->min_price ? request->min_price : null;
$max_price = request->max_price ? request->max_price : null;
$brands2 = request->brands ? request->brands : null;

$query = Product::select('field_1', 'field_2', 'field_3')
->join('brands as b', 'b.id', '=', 'products.brand_id')
...(others joins);

// here we do the search query
if($suboptions2){
    $query->where('suboptions_field', '=', $suboptions);
}

if($min_price && $max_price){
    $query->where(function($q2) {
                $q2->where('price', '>=', $min_price)
                    ->where('price', '<=', $max_price)
            });

}

if($brands2){
    $query->where('products.brand_id', '=', $brands2);
}

// others queries

// finish it with this
$query->get();

return view('front.advancesearch', compact('products', 'brands', 'options'));

我发现这样做非常有用,因为它可以很容易地实现额外的查询。

我建议您使用每一个separated,它可以帮助您轻松地操作代码

作为您的典型情况,您的sub_选项来自第三个表,使用最后一个关系

 if(count($request['suboptions'])) {

         $product->whereHas('options',function($options) use ($request) {

                   $options->whereHas('suboptions',function($suboption)use($request) {

                         $suboption->whereIn('id',$request['suboptions']);
                  });
         }); 
 }
对于最低价格最高价格,我假设您的价格在产品表中

   if(! empty($request['min_price'])) {

          $product->where('price','>=',$request['min_price']);
    }

 if(! empty($request['max_price'])) {

          $product->where('price','<=',$request['max_price']);
    }

这是我使用laravel eloquent进行多输入搜索的方法:

$input = Input::all(); //group all the inputs into single array
$product = Product::with('options','suboptions','brand');

//looping through your input to filter your product result
foreach ($input as $key => $value)
{
    if ($value!='') {
       if ($key == "max_price")
            $product = $product->where('price','<=', $value);
       elseif ($key == "min_price")
            $product = $product->where('price','>=', $value);
       elseif ($key == "brands")
            $product = $product->whereIn('brand_id', $value); //assuming that your Input::get('brands') is in array format
       elseif ($key == "suboptions")
            $product = $product->whereIn('suboption_id', $value);
    }
}
$product = $product->get();
如果未提交任何输入,上述方法将返回所有产品,并将根据输入(如果可用)过滤结果。除此之外,在继续查询之前,最好先对输入进行验证 经过数周的代码游戏,我终于找到了适合我自己的结果。在我的例子中,它对其他人有效,也许对其他建议的答案有效

public function advancedsearch(Request $request) {
    $options = Option::all();
    $brands = Brand::all();
    $brandss = Input::has('brands') ? Input::get('brands') : [];
    $suboption = Input::has('suboptions') ? (int)Input::get('suboptions') : [];
    $min_price = Input::has('min_price') ? (int)Input::get('min_price') : null;
    $max_price = Input::has('max_price') ? (int)Input::get('max_price') : null;

    //codes
    if(count($request['suboptions'])){
      $products = DB::table('products')
      ->join('product_suboption', function ($join) {
        $suboption = Input::has('suboptions') ? Input::get('suboptions') : [];
            $join->on('products.id', '=', 'product_suboption.product_id')
                 ->where('product_suboption.suboption_id', '=', $suboption);
        })
      ->paginate(12);
    }

    elseif(count($request['brands'])){
      $products = DB::table('products')
      ->whereIn('products.brand_id', $brandss)
      ->paginate(12);
    }

    elseif(count($request['min_price']) && count($request['max_price'])){
      $products = DB::table('products')
      ->whereBetween('price', [$min_price, $max_price])
      ->paginate(12);
    }


    return view('front.advancesearch', compact('products', 'brands', 'options'));
    }
注意:正如您在我的代码intInput::get'min_price'和 输入::获取“最高价格”

特别感谢Ravindra Bhanderi提出的count$request[]建议。

通过使用treats进行动态搜索非常简单,我们可以将其用于所有型号,我尽可能地动态搜索

这是任何型号都可以使用的特性

此函数将删除项目中的代码重复

也要过滤关系


我得到一个未定义的变量:min_price在SearchController的filter方法中,您必须从提交的表单I-e$min_price=$request->min_price中获取输入,然后将它们传递到查询中。在$request->min_price min_price中,min_price是您的输入名称。或者where不起作用,我们必须至少有1个where,然后说where,或者您的复选框输入字段没有设置name属性,因此您无法从中获取值,因为它们没有被发送。也许这有帮助。@Reduxx更新了我的代码。运算符和值组合非法。在$products=Product::where'price','>=',$request->min上_price@mafortis那是因为价格也是可选的,对吗?查看更新的答案是的,我在'return$q->where'id',$suboptions;`PS:我想你应该阅读我的问题更新说明。@mafortis你总是收到错误还是因为子选项的特定值?我的页面不会加载。谢谢你的回复,但是请查看我的代码,我的表单中没有产品标题输入,关于我的选项,请阅读我最新的更新说明部分。这是一个示例,实际上,你可以根据我的回答非法运算符和值组合来进行开发。如果你提供更多错误的详细信息,比如哪一行导致了错误,那将很有帮助。我猜提交的输入中有空值或空值。我已经编辑了我的答案,请随意提问,我会解释给你听
$filtered =  $products->filter(function ($product, $key) {
    return count($product->brand) > 0 && count($product->specifications) > 0;
    // add your other boolean conditions here
});

dd($filtered->toArray()); // your filtered products to return
$products = Product::orWhere('price','>=',$min_price)
->orWhere('price','<=',$max_price)
->orWhereHas('brand',function($query){
    $query->whereIn('id', $brand_ids);
})
->orWhereHas('suboptions',function($query){
    $query->whereIn('id', $suboptions_ids);
})
->orWhereHas('subspecifications',function($query){
    $query->whereIn('id', $subspecifications_ids);
})->get(); 
$products = Product::query()
    ->when($request->min_price, function ($query, $min_price) {
        return $query->where('price', '>=', $min_price);
    })
    ->when($request->max_price, function ($query, $max_price) {
        return $query->where('price', '<=', $max_price);
    })
    ->when($request->suboptions, function ($query, $suboptions) {
        $suboptionsConstraint = function ($q) use ($suboptions) {
            return $q->whereIn('id', $suboptions);
        };
        return $query->whereHas('suboptions', $suboptionsContraint)
            ->with(['suboptions' => $suboptionsContraint]);
    })
    ->when($request->brands, function ($query, $brands) {
        $brandsConstraint = function ($q) use ($brands) {
            return $q->whereIn('id', $brands);
        };
        return $query->whereHas('brands', $brandsConstraint)
            ->with(['brands' => $brandsConstraint]);
    });
public function advancedsearch(Request $request) {

$suboptions2 = request->suboptions ? request->suboptions : null;
$min_price = request->min_price ? request->min_price : null;
$max_price = request->max_price ? request->max_price : null;
$brands2 = request->brands ? request->brands : null;

$query = Product::select('field_1', 'field_2', 'field_3')
->join('brands as b', 'b.id', '=', 'products.brand_id')
...(others joins);

// here we do the search query
if($suboptions2){
    $query->where('suboptions_field', '=', $suboptions);
}

if($min_price && $max_price){
    $query->where(function($q2) {
                $q2->where('price', '>=', $min_price)
                    ->where('price', '<=', $max_price)
            });

}

if($brands2){
    $query->where('products.brand_id', '=', $brands2);
}

// others queries

// finish it with this
$query->get();

return view('front.advancesearch', compact('products', 'brands', 'options'));
 if(count($request['suboptions'])) {

         $product->whereHas('options',function($options) use ($request) {

                   $options->whereHas('suboptions',function($suboption)use($request) {

                         $suboption->whereIn('id',$request['suboptions']);
                  });
         }); 
 }
   if(! empty($request['min_price'])) {

          $product->where('price','>=',$request['min_price']);
    }

 if(! empty($request['max_price'])) {

          $product->where('price','<=',$request['max_price']);
    }
   if(count($request['brands'])) {

          $product->whereIn('brand_id',$request['brands']);
    } 
$input = Input::all(); //group all the inputs into single array
$product = Product::with('options','suboptions','brand');

//looping through your input to filter your product result
foreach ($input as $key => $value)
{
    if ($value!='') {
       if ($key == "max_price")
            $product = $product->where('price','<=', $value);
       elseif ($key == "min_price")
            $product = $product->where('price','>=', $value);
       elseif ($key == "brands")
            $product = $product->whereIn('brand_id', $value); //assuming that your Input::get('brands') is in array format
       elseif ($key == "suboptions")
            $product = $product->whereIn('suboption_id', $value);
    }
}
$product = $product->get();
public function advancedsearch(Request $request) {
    $options = Option::all();
    $brands = Brand::all();
    $brandss = Input::has('brands') ? Input::get('brands') : [];
    $suboption = Input::has('suboptions') ? (int)Input::get('suboptions') : [];
    $min_price = Input::has('min_price') ? (int)Input::get('min_price') : null;
    $max_price = Input::has('max_price') ? (int)Input::get('max_price') : null;

    //codes
    if(count($request['suboptions'])){
      $products = DB::table('products')
      ->join('product_suboption', function ($join) {
        $suboption = Input::has('suboptions') ? Input::get('suboptions') : [];
            $join->on('products.id', '=', 'product_suboption.product_id')
                 ->where('product_suboption.suboption_id', '=', $suboption);
        })
      ->paginate(12);
    }

    elseif(count($request['brands'])){
      $products = DB::table('products')
      ->whereIn('products.brand_id', $brandss)
      ->paginate(12);
    }

    elseif(count($request['min_price']) && count($request['max_price'])){
      $products = DB::table('products')
      ->whereBetween('price', [$min_price, $max_price])
      ->paginate(12);
    }


    return view('front.advancesearch', compact('products', 'brands', 'options'));
    }
public function scopeSearch($query, $keyword, $columns = [], $relativeTables = [])
{
    if (empty($columns)) {
        $columns = array_except(
            Schema::getColumnListing($this->table), $this->guarded
        );
    }   

    $query->where(function ($query) use ($keyword, $columns) {
        foreach ($columns as $key => $column) {
            $clause = $key == 0 ? 'where' : 'orWhere';
            $query->$clause($column, "LIKE", "%$keyword%");

            if (!empty($relativeTables)) {
                $this->filterByRelationship($query, $keyword, $relativeTables);
            }
        }
    });

    return $query;
}
private function filterByRelationship($query, $keyword, $relativeTables)
{
    foreach ($relativeTables as $relationship => $relativeColumns) {
        $query->orWhereHas($relationship, function($relationQuery) use ($keyword, $relativeColumns) {
            foreach ($relativeColumns as $key => $column) {
                $clause = $key == 0 ? 'where' : 'orWhere';
                $relationQuery->$clause($column, "LIKE", "%$keyword%");
            }
        });
    }

    return $query;
}