2011-02-24 118 views
13

我一直在学习如何使用准备和绑定语句来进行sql查询,到目前为止我已经发现了这个问题,它工作正常,但是当涉及到多个参数或者没有参数需要时,它根本不是动态的,如何在PHP中动态绑定mysqli bind_param参数?

public function get_result($sql,$parameter) 
    { 
     # create a prepared statement 
    $stmt = $this->mysqli->prepare($sql); 

     # bind parameters for markers 
    # but this is not dynamic enough... 
     $stmt->bind_param("s", $parameter); 

     # execute query 
     $stmt->execute(); 

    # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() 
     $meta = $stmt->result_metadata(); 

     while ($field = $meta->fetch_field()) { 
      $var = $field->name; 
      $$var = null; 
      $parameters[$field->name] = &$$var; 
     } 

     call_user_func_array(array($stmt, 'bind_result'), $parameters); 

     while($stmt->fetch()) 
     { 
      return $parameters; 
      //print_r($parameters);  
     } 


     # close statement 
     $stmt->close(); 
    } 

这是我如何调用该对象类,

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); 
$output = new search($mysqli); 

有时候,我不需要任何参数来传递,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
"; 

print_r($output->get_result($sql)); 

有时候,我只需要一个参数,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'1')); 

有时候,我只需要一个以上的参数,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
AND root_contacts_cfm.cnt_firstname = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'1','Tk')); 

所以,我认为,这条线是不是上面的动态任务,

足够的动态
$stmt->bind_param("s", $parameter); 

要动态地构建bind_param,我在其他帖子上发现了这个。

call_user_func_array(array(&$stmt, 'bind_params'), $array_of_params); 

我试图从php.net修改一些代码,但我越来越行不通,

if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+ 
    { 
     $refs = array(); 
     foreach($arr as $key => $value) 
      $array_of_param[$key] = &$arr[$key]; 

     call_user_func_array(array(&$stmt, 'bind_params'), $array_of_params); 

    } 

为什么?任何想法,我怎么能使它工作?

或者也许有更好的解决方案?

回答

17

发现mysqli的答案:

public function get_result($sql,$types = null,$params = null) 
    { 
     # create a prepared statement 
     $stmt = $this->mysqli->prepare($sql); 

     # bind parameters for markers 
     # but this is not dynamic enough... 
     //$stmt->bind_param("s", $parameter); 

     if($types&&$params) 
     { 
      $bind_names[] = $types; 
      for ($i=0; $i<count($params);$i++) 
      { 
       $bind_name = 'bind' . $i; 
       $$bind_name = $params[$i]; 
       $bind_names[] = &$$bind_name; 
      } 
      $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); 
     } 

     # execute query 
     $stmt->execute(); 

     # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() 
     $meta = $stmt->result_metadata(); 

     while ($field = $meta->fetch_field()) { 
      $var = $field->name; 
      $$var = null; 
      $parameters[$field->name] = &$$var; 
     } 

     call_user_func_array(array($stmt, 'bind_result'), $parameters); 

     while($stmt->fetch()) 
     { 
      return $parameters; 
      //print_r($parameters);  
     } 


     # the commented lines below will return values but not arrays 
     # bind result variables 
     //$stmt->bind_result($id); 

     # fetch value 
     //$stmt->fetch(); 

     # return the value 
     //return $id; 

     # close statement 
     $stmt->close(); 
    } 

则:

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); 
$output = new search($mysqli); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
ORDER BY cnt_id DESC 
"; 
print_r($output->get_result($sql)); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'s',array('1'))); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
AND root_contacts_cfm.cnt_firstname = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql, 'ss',array('1','Tk'))); 

mysqli的真差劲,当谈到这一点。我想我应该迁移到PDO!

+0

您params数组中的空值将打破您的动态绑定调用FYI – 2014-12-16 21:02:32

3

或者也许有更好的解决方案?

这个答案对你没有太大帮助,但是你应该认真考虑从mysqli切换到PDO

这样做的主要原因是因为PDO通过内置函数执行mysqli中要做的事情。除了manual param binding之外,execute method也可以接受一系列参数。

PDO很容易扩展,并且添加便捷方法来获取所有内容并返回,而不是执行准备执行舞蹈非常容易。

+0

的问题是,PDO是** **得多比mysqli的慢。甚至比旧的mysql慢。 – 2013-04-02 11:23:10

+1

@Julian:说“PDO”慢得多[有点多](http://jnrbsn.com/2010/06/mysqli-vs-pdo-benchmarks)。性能差异太小,可能成为主要瓶颈(如果明显的话) – 2013-09-11 10:01:10

+1

感谢您的纠正。我读了一个基准,其中差异更为显着。我自己的测试结果更为显着。 – 2013-09-12 09:50:30

5

使用PHP 5.6,您可以通过unpacking operator...$var)和get_result() insted bind_result()

public function get_result($sql,$types = null,$params = null) { 
    $stmt = $this->mysqli->prepare($sql); 
    $stmt->bind_param($types, ...$params); 

    if(!$stmt->execute()) return false; 
    return $stmt->get_result(); 

} 

实施例:

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); 
$output = new search($mysqli); 


$sql = "SELECT * FROM root_contacts_cfm WHERE root_contacts_cfm.cnt_id = ? 
     AND root_contacts_cfm.cnt_firstname = ? 
     ORDER BY cnt_id DESC"; 

$res = $output->get_result($sql, 'ss',array('1','Tk')); 
while($row = res->fetch_assoc()){ 
    echo $row['fieldName'] .'<br>'; 
}