【问题标题】:mysqli : bind param where search parameters are conditionalmysqli:绑定参数,其中搜索参数是有条件的
【发布时间】:2013-07-04 23:08:30
【问题描述】:

我需要一个好的结构来构建查询,其中搜索参数是有条件的,使用 mysqli 准备好的语句$query -> bind_param('sss',$date,$time,$place);

我不知道如何按顺序应用'sss''$date,$time,$place' 参数。你能把它们作为变量传递吗?

旧的 MySQL 方式:

<?php

// date is obligatory

$date = mysql_real_escape_string($_GET["date"]);

$query="SELECT * FROM dbase WHERE date='$date'"; 

// time field is custom

if(!empty($_GET["time"])) {

    $time= mysql_real_escape_string($_GET["time"]);
    $buildQuery[] = "time='$time'";

}

// place field is also custom

if(!empty($_GET["place"])) {

    $place= mysql_real_escape_string($_GET["place"]);
    $buildQuery[] = "place='$place'";

}

// building query

if(!empty($build)) {

    $query .= ' AND '.implode(' AND ',$build).' ORDER BY date';

}

?>

【问题讨论】:

    标签: php mysqli


    【解决方案1】:

    这是一个很好的例子,其中 PDO 比 MySQLi 容易得多:

    $query="SELECT * FROM dbase";
    $terms = array("date" => $date);
    $params = array();
    
    // time field is custom
    
    if(isset($_GET["time"])) {
        $terms["sType"] = $time;
    }
    
    // place field is also custom
    
    if(isset($_GET["place"])) {
        $terms["place"] = $place;  
    }
    
    // building query
    
    if(!empty($terms)) {
        $query .= "WHERE " . implode(" AND ", 
            array_map(function($term) { return "$term = ?"; }, array_keys($terms));
        $params = array_values($terms);
    }
    $query .= "ORDER BY date";
    
    $stmt = $pdo->pepare($query);
    $stmt->execute($params);
    

    PS:我不得不质疑您是否打算让您的 sType 列同时包含 timeplace。似乎您正在破坏关系数据库的最佳实践。除非这只是一个错字。

    【讨论】:

      【解决方案2】:

      未经测试,但你应该可以做这样的事情

      $types = array();
      $vals = array();
      
      if(isset($_GET["time"])) {
          $types[] = 's';
          $vals[] = $_GET["time"];
          $buildQuery[] = "sType = ?";
      }
      
      //...etc...
      
      $args = array_merge(array(join($types)), $vals);
      $callable = array($mysqli, 'bind_param');
      call_user_func_array($callable, $args));
      

      http://php.net/manual/en/language.types.callable.php

      但是,还有另一种方法。只需在 sql 中使用逻辑:

      select *
      from tbl
      where (date = ? or ? = '')
        and (time = ? or ? = '')
        and (place = ? or ? = '')
      

      以上假设您将每个 arg 绑定两次,并将它们绑定为字符串,但如果未设置查询字符串参数,则绑定一个空字符串...如果需要,您也可以通过类似 (date = ? or ? is null) 的方式将它们绑定为 null .

      $mysqli->bind_param('ssssss', $date,$date, $time,$time, $place,$place);
      

      ps,mysql 优化器会简化这个简单的逻辑。

      【讨论】:

      • 第一个例子怎么用?
      【解决方案3】:

      根据 goat 的回复,这是一个完整且经过测试的答案,其中包含 UPDATE 语句,其中要更新的字段是有条件的。我使用了一个非常简单的表结构,其中包含 3 个字段:ID(自动增量)、Varchar1(varchar255)和 Varchar2(varchar255)。在这个脚本中,我想更新前三个记录的两个 varchar 字段。基于此脚本,很容易有条件地添加或删除要更新的字段。

      $mysqli = new mysqli(...);
      
      $types = array();
      $vals = array();
      $query = array();
      
      // varchar1
      $types[] = 's';
      $vals[] = 'foo1';
      $query[] = "varchar1=?";
      
      // varchar2
      $types[] = 's';
      $vals[] = 'foo2';
      $query[] = "varchar2=?";
      
      $sql = "UPDATE test SET ".implode(",", $query)." WHERE id IN (1,2,3)";
      $stmt = $mysqli->prepare($sql);
      
      $args = array_merge(array(implode($types)), $vals);
      
      $callable = array($stmt, 'bind_param');
      call_user_func_array($callable, refValues($args));
      
      $stmt->execute();
      
      function refValues($arr) {
          if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+ 
          { 
              $refs = array(); 
              foreach($arr as $key => $value) 
                  $refs[$key] = &$arr[$key]; 
              return $refs; 
          } 
          return $arr; 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-01
        • 2010-12-03
        • 2012-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多