我正在尝试将一年前制作的复杂php文件转换为准备好的语句。参数将像这样传递:
file.php?name=John&age=20
但是,可能还有更多可能使用的参数。工作,地址,电话号码等。这是我容易与准备好的陈述混淆的地方。
例如:
$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";
if (isset($_REQUEST['name'])) {
$query .= " and name = ?";
}
if (isset($_REQUEST['age'])) {
$query .= " and age = ?";
}
if (isset($_REQUEST['address'])) {
$query .= " and address = ?";
}
$stmt = $db->prepare($query);
$stmt->bind_param('sis', $_REQUEST['name'], $_REQUEST['age'], $_REQUEST['address']);
$stmt->execute();
这里的问题是bind_param
,因为我不知道可能有多少个参数可用。
我将如何以合理的方式解决这个问题?
答案 0 :(得分:2)
一个很好的问题。解决方案非常简单。
您需要的称为argument unpacking operator。它将允许您对bind_param
使用任意长度的数组。您需要做的就是将可接受的参数收集到数组中,然后动态创建类型字符串,最后使用上述运算符:
$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";
$params = array();
if (isset($_REQUEST['name'])) {
$query .= " and name = ?";
$params[] = $_REQUEST['name'];
}
if (isset($_REQUEST['age'])) {
$query .= " and age = ?";
$params[] = $_REQUEST['age'];
}
if (isset($_REQUEST['address'])) {
$query .= " and address = ?";
$params[] = $_REQUEST['address'];
}
if ($params)
$stmt = $db->prepare($query);
$types = str_repeat("s", count($params));
$stmt->bind_param($types, ...$params);
$stmt->execute();
$result = $stmt->get_result();
} else {
$result = $db->query($query);
}
答案 1 :(得分:1)
对于选择查询,我认为您不需要获取所有参数,获取ID或姓名或职位名称就足以列出,我的意思是单个参数可能是两个。
但是插入那么多的值会很痛苦,所以,我将使用如下函数:
此函数对数组和绑定中的值进行计数。
function bindQueryParams($sql, $param_type, $param_value_array) {
$param_value_reference[] = & $param_type;
for($i=0; $i<count($param_value_array); $i++) {
$param_value_reference[] = & $param_value_array[$i];
}
call_user_func_array(array(
$sql,
'bind_param'
), $param_value_reference);
}
此函数插入:
function insert($query, $param_type, $param_value_array) {
$sql = $this->conn->prepare($query);
$this->bindQueryParams($sql, $param_type, $param_value_array);
$sql->execute();
}
Usaqe:
$query = "INSERT INTO tbl_token_auth (username, password_hash, selector_hash, expiry_date) values (?, ?, ?,?)";
$result = insert($query, 'ssss', array($username, $random_password_hash, $random_selector_hash, $expiry_date));
更新:我的函数可以像这样用于选择:
function runQuery($query, $param_type, $param_value_array) {
$sql = $this->conn->prepare($query);
//This function calling bindQueryParams function and auto creating binds
$this->bindQueryParams($sql, $param_type, $param_value_array);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$results[] = $row;
}
}
if(!empty($results)) {
return $results;
}
}
Usaqe:
$query = "Select * from your table where name = ?";
//You just need to variables in array
$result = runQuery($query, 's', array($your_variables));
答案 2 :(得分:-1)
好吧,该过程将与构建$query
变量的过程非常相似-即一次将一个变量添加到参数列表中。
考虑bind_param
需要做两件事:
首先是一个简单字符串形式的数据类型列表。因此,您只需为每个参数添加一个字符串变量,然后将其最后传递给bind_param。
第二个是参数列表。这比较棘手,因为您不能仅向bind_param提供数组。但是,您可以创建自己的数组,然后使用call_user_func_array将其转换为平面列表。
这是我之前写的(效果不错)。请注意,它会尝试检测参数类型并创建合适的字符串,但是您可以根据需要在if
语句中手动构建字符串:
$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";
$params = array();
if (isset($_REQUEST['name'])) {
$query .= " and name = ?";
$params[] = $_REQUEST['name'];
}
if (isset($_REQUEST['age'])) {
$query .= " and age = ?";
$params[] = $_REQUEST['age'];
}
if (isset($_REQUEST['address'])) {
$query .= " and address = ?";
$params[] = $_REQUEST['address'];
}
$stmt = $db->prepare($query);
if (!is_null($params))
{
$paramTypes = "";
foreach ($params as $param)
{
$paramTypes .= mysqliContentType($param);
}
$bindParamArgs = array_merge(array($paramTypes), $params);
//call bind_param using an unpredictable number of parameters
call_user_func_array(array(&$stmt, 'bind_param'), getRefValues($bindParamArgs));
}
$stmt->execute();
function mysqliContentType($value)
{
if(is_string($value)) $type = 's';
elseif(is_float($value)) $type = 'd';
elseif(is_int($value)) $type = 'i';
elseif($value == null) $type = 's'; //for nulls, just have to assume a string. hopefully this doesn't mess anything up.
else throw new Exception("type of '".$value."' is not string, int or float");
return $type;
}
function getRefValues($arr)
{
$refs = array();
foreach($arr as $key => $value)
{
$refs[$key] = &$arr[$key];
}
return $refs;
}