如何将MySQLI准备的语句的结果放入关联阵列中?
-
13-09-2019 - |
题
我有一个SQL查询和MySQLI准备的声明:
$sql = 'SELECT photographers.photographer_id, photographers.photographer_name
FROM photographers';
$stmt = $conn->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_result($photographer_id, $photographer_name);
$OK = $stmt->execute();
$stmt->fetch();
}
如何将结果存储在关联阵列中,以便以后循环并获取SQL字符串返回的所有数据?
解决方案
尝试以下操作:
$meta = $statement->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($statement, 'bind_result'), $params);
while ($statement->fetch()) {
foreach($row as $key => $val) {
$c[$key] = $val;
}
$hits[] = $c;
}
$statement->close();
首先,您可以获得查询元数据,然后从中获得您获取的所有字段(您可以手动执行此操作,但是此代码适用于所有查询,而不是手工构建)。这 call_user_func_array()
函数调用 mysqli_stmt::bind_result()
在每个参数中为您函数。
之后,这只是一行奔跑并为每一行创建一个关联数组,并将其添加到导致所有结果的数组中。
其他提示
更新: 由于PHP 5.3.0,您可以获得提供Fetch_Array方法的MySqli_Result对象。
$sql = 'SELECT photographers.photographer_id, photographers.photographer_name
FROM photographers';
$data = null;
$stmt = $conn->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_result($photographer_id, $photographer_name);
$OK = $stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_array();
}
我遇到了此讨论,以找到一种解决方法,以获取MySQLI准备的语句中的数据,而无需MySQLND。我一直在开发一堂课,以方便地使用MySqli处理准备好的陈述。请查看代码,或者简单地使用它(请参见代码末尾的用法示例),以便快速编写准备好的语句并获得结果。
class DbUtils {
private $host;
private $user;
private $pass;
private $database;
private $connection;
public function __construct($host, $user, $pass, $database) {
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->database = $database;
$this->connection = new mysqli($host, $user, $pass, $database);
}
public function query(Array $params) {
$args = array();
// 0. Correct the input function parameters
if (array_key_exists("query", $params)) {
$args["query"] = $params["query"];
} else {
throw new Exception("Parameter not found: 'query'.");
}
if (array_key_exists("types", $params)) {
$args["types"] = $params["types"];
} else {
$args["types"] = '';
}
if (array_key_exists("input", $params)) {
$args["input"] = $params["input"];
} else {
$args["input"] = array();
}
// 1. Check the connection:
if ($this->connection->connect_errno) {
echo "Connection to MySQL failed: [" . $this->connection->connect_errno . "]: " . $this->connection->connect_error . "<br/>";
}
// 2. Prepare the sentence:
if (!($stmt = $this->connection->prepare($args["query"]))) {
echo "Prepared statement failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>";
}
// 3. Bind the input parameters:
if ( ( 0 != sizeof( $args["input"] ) ) && !(call_user_method_array("bind_param", $stmt, array_merge(array($args["types"]), $args["input"])))) {
echo "Binding parameters failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>";
}
// 4. Execute the sentence
if (!($stmt->execute())) {
echo "Sentence execution failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>";
}
// 5. Bind the results:
$data = array();
$meta = $stmt->result_metadata();
$row = array();
while( $field = $meta->fetch_field() ) {
$argos[] = &$row[$field->name];
}
call_user_method_array('bind_result', $stmt, $argos);
// 6. Collect the results:
while ($stmt->fetch()) {
foreach($argos as $key => $val) {
$dataItem[$key] = $val;
}
$data[] = $dataItem;
}
// 7. Close the sentence:
$stmt->close();
// 8. Return interesting data properly ordered:
return $data;
}
}
// 1. Instantiate it:
$dbUtils = new DbUtils(
"127.0.0.1",
"user",
"password",
"database"
);
// 2. Query prepared statements like this:
$users = $dbUtils->query(array(
"query" => "SELECT * FROM user WHERE name LIKE ? AND pass LIKE ?;",
"input" => array('%', '%'),
"types" => 'ss'
));
// 3. Enjoy securely CRUD Ops!
奇怪的是,你不能。根本无法从mysqli_stmt实例获得mySqli_Result对象。我一直认为这是一个主要缺陷,并且猜测这是Mysqli从未获得任何真正受欢迎的主要原因之一。如今,PDO几乎取代了PDO,它可以通过努力来实现您想要的一切。
编辑: 我的答案仅意味着您默认情况下不能这样做。当然,您可以像克里斯的建议一样自己实施它。尽管如此,如果可能的话,我认为您应该使用PDO。
如果您无法使用PDO扩展。或者,您在使用准备好的语句的情况下构建数据库类困难。如何用于插入更新,删除和插入:
$db = new database();
$db->query = "INSERT INTO blabla (name,date,number) VALUES(?,?,?)";
$db->params = array($name,$date,$number);
$db->type = 'ssi'; //s=string,i=integer
if($db->insert())
echo 'success';
获取作品有些不同
$array = array();
$db = new database();
$db->query = "SELECT * FROM blabla WHERE id=? and someother=?";
$db->params = array($id,$other);
$db->type = 'is';
$r = $db->fetch();
//$r[0]['id'] for row 1
//$r[0]['name'] for row 1
//$r[1] .... For row 2
//$r[2] .... For row 3
//etc...
现在为数据库类
class database {
private $stmt;
private $mysqli;
private $query;
private $params = array();
private $type;
public function __set($name, $value) {
switch ($name) {
case 'params':
$this->params = $value;
break;
case 'query':
$this->query = $value;
break;
case 'type':
$this->type = $value;
break;
default:
break;
}
}
public function __get($name) {
if ($name !== "mysqli" && $name !== "stmt")
return $this->$name;
}
public function __construct() {
$this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);
$this->stmt = $this->mysqli->stmt_init();
}
private function close_con($bool) {
if ($bool) {
$this->stmt->free_result();
}
$this->stmt->close();
$this->mysqli->close();
}
private function nofetch() {
$this->stmt->prepare($this->query);
$bind_names[] = $this->type;
for ($i = 0; $i < count($this->params); $i++) {
$bind_name = 'bind' . $i;
$$bind_name = $this->params[$i];
$bind_names[] = &$$bind_name;
}
call_user_func_array(array($this->stmt, "bind_param"), $bind_names);
if ($this->stmt->execute()) {
$this->close_con(false);
return true;
}
$this->close_con(false);
return false;
}
public function insert() {
if ($this->nofetch()) {
return true;
}
return false;
}
public function update() {
if ($this->nofetch()) {
return true;
}
return false;
}
public function delete() {
if ($this->nofetch()) {
return true;
}
return false;
}
public function fetch() {
$result_out = array();
$this->stmt->prepare($this->query);
$bind_names[] = $this->type;
if (count($this->params) > 0) {
for ($i = 0; $i < count($this->params); $i++) {
$bind_name = 'bind' . $i;
$$bind_name = $this->params[$i];
$bind_names[] = &$$bind_name;
}
call_user_func_array(array($this->stmt, "bind_param"), $bind_names);
}
if ($this->stmt->execute()) {
$result = $this->stmt->result_metadata();
$cols = $result->fetch_fields();
foreach ($cols as $col) {
$name = str_replace("-", "_", $col->name);
$$name = null;
if ($name == null)
$name = 'name';
$bindarray[$name] = &$$name;
}
call_user_func_array(array($this->stmt, 'bind_result'), $bindarray);
$this->stmt->store_result();
$copy = create_function('$a', 'return $a;');
while ($this->stmt->fetch()) {
$result_out[] = array_map($copy, $bindarray);
}
}
$this->close_con(true);
return $result_out;
}
}
我希望这是有帮助的
一个简单的方法,实际上是出乎意料的。我知道这是程序性的,但仍然:
$query = "SELECT * FROM foo WHERE bar = ?;";
$stmt = mysqli_prepare($dbc, $query);
mysqli_stmt_bind_param($stmt, "s", $bar);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
return mysqli_fetch_assoc($result);
https://stackoverflow.com/users/5849505/carl-gentleman
他的答案是PHP先前版本的一种方法,因为“ Call_user_method_array”已在PHP 4.1.0中弃用,并在PHP 7.0.0中删除。
因此,我发现至少在PHP7上发布更新的答案是相关的,因为我最近发现自己没有我转移到的新主机上的MySQLI扩展的MySQLND本地驱动程序。耶!...
注意:这里有2个功能。最后一个是必需的。这是我知道这一切的唯一方法。 (编辑答案不会产生关联阵列...固定)
public function arr($query, $data, $format) { // Some parts have been used from others. I don't know who.
$d = array();
$row = array();
// 1. Connect to the database // This is how I do it
$db = $this->con;
// 2. Prepare the sentence:
if( !($stmt = $db->prepare($query)) ) {
echo "Prepared statement failed: [" . $stmt->errno . "]: " . $stmt->error . "<br>";
$d[0] = false;// I return an object array so [0] I can check later. It is true or false however I define it.
return $d;
}
// cast to array
$data = (array) $data;
$format = (array) $format;
//Normalize format
$format = implode('', $format);
$format = str_replace('%', '', $format);
// Prepend $format onto $values
array_unshift($data, $format);
// 3. Bind the input parameters: (note "call_user_func_array" is not depriciated)
if ( !(call_user_func_array( array( $stmt, 'bind_param'), $this->ref_values($data) )) ) {
echo "Binding parameters failed: [" . $stmt->errno . "]: " . $stmt->error . ";<br>";
}
// 4. Execute the sentence
if ( !($stmt->execute()) ) {
echo "Sentence execution failed: [" . $stmt->errno . "]: " . $stmt->error . ";<br>";
}
// 5. Prepare to Bind the results:
$meta = $stmt->result_metadata();
while( $field = $meta->fetch_field() ) {
$argos[] = &$row[$field->name];
$fld_nms[] = $field->name;
}
// 6. Bind the results to the argos array:
call_user_func_array( array( $stmt, 'bind_result'), $argos);
/* // I left some debuging tools that are helpful
echo "<br>argos<br>";
print_r($argos);
echo "<br><br>";
$class_methods = get_class_methods($stmt);
foreach ($class_methods as $method_name) {
echo "$method_name<br>";
}
*/
// 7. Collect the results:
while ($ftch = $stmt->fetch()) {
$dataItem = array();
/*
echo "<br>ftch<br>";
print_r($ftch);
echo "<br><br>";
*/
foreach($argos as $key => $val) {
echo "Args: k:" . $key . "; v:" . $val . ";<br>";
$nme = $fld_nms[$key];
$dataItem[$nme] = $val;
//$dataItem[$key] = $val;
}
$d[] = $dataItem; // I am not interested in returning the multi level array yet but I left it
}
// 8. Close the sentence:
$stmt->close();
// 9. Return interesting data properly ordered:
return $d;
}
private function ref_values($array) {
$refs = array();
foreach ($array as $key => $value) {
$refs[$key] = &$array[$key];
}
return $refs;
}