【问题标题】:Search and filter data using mysql and php使用 mysql 和 php 搜索和过滤数据
【发布时间】:2020-05-16 11:16:55
【问题描述】:

我刚刚开始学习 php 和 mysql,并且正在使用 php 和 mysql 创建一个项目。我在从数据库中搜索和过滤数据时卡住了。搜索基本上是一个组合搜索并根据用户输入过滤数据。

这是我的代码:

public function filterSearch(Request $request){
    $new  =  $request->get('new');
    $used  =  $request->get('used');
    $registered  =  $request->get('registered');
    $make = $request->get('make');
    $model = $request->get('model');
    $price = $request->get('price');
    $city =  $request->get('city');
    $registration = $request->get('firstRegistration');

    $query =  DB::select("SELECT  * FROM ads WHERE vehicleCond LIKE '".$new."' OR vehicleCond LIKE '".$used."' OR vehicleCond LIKE '".$registered."' ");
    $decode =  json_decode(json_encode($query),true);
    $finalArr = array();
    for($i=0; $i<count($decode); $i++){
        if($make || $model || $registration){
            if(($decode[$i]['make'] == $make) || ($decode[$i]['model'] == $model) ||  ($decode[$i]['registration'] == $registration)){
                array_push($finalArr,$decode[$i]);
            }
        }else{
            array_push($finalArr,$decode[$i]);
        }   
    }
    return response()->json(['success'=>$finalArr], 200);

   }

结果不正确...对于单选,它工作正常。当我使用组合时,结果不正确。

【问题讨论】:

  • LIKE 用于匹配模式。使用= 进行精确匹配。
  • “这是我的代码”。好的,你有什么问题?
  • 我假设您使用的是 Laravel,因为查询生成器的语法似乎很熟悉。坦率地说,您需要重新阅读 Laravel 文档,因为这正是不使用 Laravel 的查询构建器的方法——忽略您的代码错误的事实,如果它可以工作,那么它极容易发生 SQL 注入。
  • @Barmar:问题已更新
  • 向我们展示为失败的案例生成的 SQL。

标签: php mysql filter


【解决方案1】:

我假设您需要动态查询/过滤器。

您的 html 脚本可以遵循以下模式/格式:

<input type="checkbox" name="filter1" value="new">
<input type="checkbox" name="filter1" value="used">
<input type="checkbox" name="filter1" value="pre-registered">

<select name="filter2" id="">...</select>
<select name="filter3" id="">...</select>

在 PHP 文件中,您可以使用一些条件来附加查询条件/过滤器:

$criteria = "";
if($request->get('filter1'))
{
    $criteria .= " AND `filter1` = '".addslashes($request->get('filter1'))."'";
}

if($request->get('filter2'))
{
    $criteria .= " AND `filter2` = '".addslashes($request->get('filter2'))."'";
}

//and so on...

//output
$query =  DB::select("SELECT * FROM your_table WHERE 1 = 1 {$criteria}");

注意事项:

你可能需要小心形成 $criteria 因为它可能仍然有机会使用 DB::select 方法获得 Sql Injection,但我相信你可以使用使用 Laravel Eloquent 方法适应相同的逻辑。

【讨论】:

  • addslashes 是干什么用的?
  • 因为我们使用的是 DB::select,所以我添加了一个额外的步骤来防止 SQL 注入。通过使用添加斜杠,此函数将在检测到字符串中的任何引号时在字符串上添加 \。 php.net/manual/en/function.addslashes.php
  • 这是一种非常古老的对抗 SQL 注入的方法。 DB::select() 支持预处理语句。
【解决方案2】:

这是您问题的解决方案


    public function filterSearch(Request $request){
        $make = $request->get('make');
        $model = $request->get('model');
        $price = $request->get('price');
        $city =  $request->get('city');
        $registration = $request->get('firstRegistration');
        $searchFields = [
            'new',
            'used',
            'registered'
        ];

        $query =  DB::table('ads')->where(function ($query) use ($searchFields, $request) {
                collect($searchFields)->each(function($field) use($likeCriteria, $query) {
                    $likeCriteria = $request->get($field);
                    if ($likeCriteria === '') {
                        $likeCriteria = '%';
                    }

                    $query->orWhere($field, 'like', '%' . $likeCriteria . '%');
                });
            })->get();

        $decode =  json_decode(json_encode($query),true);
        $finalArr = array();
        for($i=0; $i<count($decode); $i++){
            if($make || $model || $registration){
                if(($decode[$i]['make'] == $make) || ($decode[$i]['model'] == $model) ||  ($decode[$i]['registration'] == $registration)){
                    array_push($finalArr,$decode[$i]);
                }
            }else{
                array_push($finalArr,$decode[$i]);
            }   
        }
        return response()->json(['success'=>$finalArr], 200);
    }

  • 首先,将所有要搜索的变量移到数组$searchFields 中,这样我们就可以避免代码重复,使用干净的代码。
  • 更改您的 DB 查询,以便我们可以使用 table 方法,然后使用带有查询功能的 where 来移动其中的所有逻辑,同时避免 SQL 注入。

在此链接上,您可以了解更多信息:https://laravel.com/docs/7.x/queries#where-clauses

如果您有任何问题,请告诉我。

【讨论】:

    【解决方案3】:

    我会改变这个:

    $new  =  $request->get('new');
    $used  =  $request->get('used');
    $registered  =  $request->get('registered');
    $make = $request->get('make');
    $model = $request->get('model');
    $price = $request->get('price');
    $city =  $request->get('city');
    $registration = $request->get('firstRegistration');
    

    到这里:

        $new  =  (empty($request->get('new')) ? "%" : $request->get('new');
        $used  =  (empty($request->get('used')) ? "%" : $request->get('used');
        $registered  =  (empty($request->get('registered')) ? "%" : $request->get('registered');
        $make = (empty($request->get('make')) ? "%" : $request->get('make');
        $model = (empty($request->get('model')) ? "%" : $request->get('model');
        $price = (empty($request->get('price')) ? "%" : $request->get('price');
        $city =  (empty($request->get('city')) ? "%" : $request->get('city');
        $registration = (empty($request->get('firstRegistration')) ? "%" : $request->get('firstRegistration');
    

    【讨论】:

      【解决方案4】:

      我会尝试将查询存储到一个变量中,然后使用三元条件或三元 if 添加选择 if isset 或非空

      $query=""SELECT  * FROM ads WHERE 1=1 ";
      $query.=(isset($new) && $new!='' ? " OR vehicleCond LIKE '%" . $new . "%'" : "");
      $query.=(isset($used) && $used!='' ? " OR vehicleCond LIKE '%" . $used. "%'" : "");
      $query.=(isset($registered) && $registered!='' ? " OR vehicleCond LIKE '%" . $registered. "%'" : "");
      //and so on depends on your selection variables
      //after that
      $query =  DB::select($query);
      

      干杯

      【讨论】:

        猜你喜欢
        • 2012-05-09
        • 1970-01-01
        • 1970-01-01
        • 2021-06-06
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 2014-04-04
        • 1970-01-01
        相关资源
        最近更新 更多