簡體   English   中英

在 PHP PDO 中,如何在不知道名稱的情況下綁定准備好的語句的命名參數?

[英]In PHP PDO, how can I bind named parameters of a prepared statement without knowing their names?

我正在嘗試編寫一個輔助查詢函數來將結果集返回給調用者,但是當調用者使用命名參數提供准備好的語句時,我不確定如何將它們綁定到函數中。

function queryDB(string $query, array $param=null) {
  
  global $dbh; //reference the db handle declared in init.php 

  if (isset($param)) { //query params provided, so a prepared statement
    
    $stmt = $dbh->prepare($query);
    for($i = 1; $i <= count($param);$i++) { //bind the parameters 1-by-1
      $stmt->bindParam($i, $param[$i]); //
    }
    $stmt->execute();

  } else { //a straight sql query, not a prepared statement

    $stmt = $dbh->query($query);   

  }
  $result = $stmt->fetchAll();
  return $result;
}

如果我使用未命名參數准備好的語句調用queryDB($query, [$name, $age]) ,例如$query = INSERT INTO users (name, age) VALUES(?, ?)$name = "trump"; $age = 18 $name = "trump"; $age = 18 ,該代碼應該可以工作。

但是有時我(或其他人)會使用命名參數准備好的語句調用,例如$query = INSERT INTO users (name, age) VALUES(:name, :age)$name = "trump"; $age = 18 $name = "trump"; $age = 18 現有的 bindParam(i, $value) 不應該工作,但函數不會知道那些:name, :age, :whatever命名參數。 我應該如何編寫bindParam(param, value)以容納命名和未命名的准備語句? 假設 params 將按匹配的順序提供,即使命名。


根據@Dharman 的評論功能更新


/*
Helper function to query database and return the full resultset.
@param $query: the SQL query string, can be either a straight query (without any external inputs) or a prepared statement using either named parameters (:param) or positional (?)
@param $param: the values, in array, to bind to a prepared statement, [value1, value2, ...] or ["name1" => value1, "name2" => value2, ...] for positional or named params
@return full resultset of the query
*/
function queryDB(string $query, array $param=null) {
  
  global $dbh; //reference the db handle declared in init.php 

  if (isset($param)) { //query params provided, so a prepared statement
    
    $stmt = $dbh->prepare($query); //set up the prepared statement

    $isAssocArray = count(array_filter(array_keys($param), "is_string")) == 0 ? false : true; //boolean flag for associative array (dict, with keys) versus sequential array (list, without keys)  
    
    if ($isAssocArray) { //the prepared statement uses named parameters (:name1, :name2, ...)
      
      foreach($param as $name => $value) { //bind the parameters 1-by-1
        if (substr($name, 0, 1) != ":") { //if the provided parameter isn't prefixed with ':' which is required in bindParam()
          $name = ":".$name; //prefix it with ':'
        }
        $stmt->bindParam($name, $value);
      }

    } else { //the prepared statement uses unnamed parameters (?, ?, ...) 
      
      for($i = 1; $i <= count($param); $i++) { //bind the parameters 1-by-1
        $stmt->bindParam($i, $param[$i]); 
      }

    } //the prepared statement has its values bound and ready for execution

    $stmt->execute();

  } else { //not a prepared statement, a straight query

    $stmt = $dbh->query($query);   

  }

  $resultset = $stmt->fetchAll();
  return $resultset;

}

絕對沒有理由使用bindParam

如果您的 SQL 已命名占位符,那么您的數組必須是關聯的。 你需要這樣稱呼它:

queryDB($query, ['name' => $name, 'age' => $age]);

然后您可以使用foreach($params as $key => $value) bindParam並使用bindParam但正如我所說,絕對沒有理由使用它。

相反,將數組傳遞給execute

function queryDB(PDO $dbh, string $query, ?array $param = null)
{
    $stmt = $dbh->prepare($query);
    $stmt->execute($param);
    return $stmt->fetchAll();
}

PS 您甚至可以刪除if語句和對query的調用。 此方法與prepareexecute prepare同樣的事情。 沒有理由在您的代碼中出現這樣的特殊情況。

暫無
暫無

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

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