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();
}
ドキュメンテーション: http://php.net/manual/en/mysqli-stmt.get-result.php
私は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拡張モジュールを使用することができない場合。それとも、トラブルプリペアドステートメントを使用して、データベースのクラスを構築をしています。 どのように削除、挿入、更新のために使用して挿入します:
$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 の
彼の答えは「call_user_method_array」としてPHPの以前のバージョンのための一つの方法は、PHP 4.1.0で非推奨とPHP 7.0.0で削除されたされます。
だから、私は最近、私がに転送した新しいホスト上のmysqliのの拡張子のためのMYSQLNDネイティブドライバなしで自分自身を発見したことから、少なくともPHP7のために、それが関連する更新の答えを投稿する見つけます。イェーイ!...
注意:ここでは2つの機能があります。最後の1つが必要になります。それは私がそれがすべて動作するように知っている唯一の方法です。
(答えを編集すると、連想配列...固定を生成しません) 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;
}