How to get Mysqli Stmt to fetch multiple rows correctly?
I've been reaching the end of my ideas with this crazy problem.
Using mysqli I run the following query
SELECT * FROM `shop_cart` WHERE `tmpID`=?
It should return each row in an array like this:
Array
(
[0] => Array
(
[id] => 1
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 800
[qty] => 2
[time] => 1310076898
)
[1] => Array
(
[id] => 2
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 797
[qty] => 1
[time] => 1310076903
)
[2] => Array
(
[id] => 3
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 883
[qty] => 1
[time] => 1310076907
)
[3] => Array
(
[id] => 4
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 795
[qty] => 1
[time] => 1310076909
)
)
Instead I get four copies of the same row like this:
Array
(
[0] => Array
(
[id] => 4
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 795
[qty] => 1
[time] => 1310076909
)
[1] => Array
(
[id] => 4
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 795
[qty] => 1
[time] => 1310076909
)
[2] => Array
(
[id] => 4
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 795
[qty] => 1
[time] => 1310076909
)
[3] => Array
(
[id] => 4
[tmpID] => af83abab7fdee8eb0cf8919f171cdeec
[pID] => 795
[qty] => 1
[time] => 1310076909
)
)
The problem lies somewhere in this bit of code I think:
while ($query->fetch()){
$results[] = $fields;
}
If I put print_r($fields)
in like this:
while ($query->fetch()){
print_r($fields);
$results[] = $fields;
}
It prints each row of the results correctly. But if I put print_r($results)
in here like this:
while ($query->fetch()){
$results[] = $fields;
}
print_r($results);
...then I get one large array containing duplicate copes of only one row. It seems to me that the $results array isn't getting populated correctly. It seems that the data is coming out of the database okay.
Any help would be great, I'm really at the end of my rope at figuring this out!
Edit
Here's some more code preceding (and including) the fetch() loop as posted above.
// Generate Types
$types = ''; //initial sting with types
foreach($params as $param) { //for each element, determine type and add
if(is_int($param)) {
$types .= 'i'; //integer
} elseif (is_float($param)) {
$types .= 'd'; //double
} elseif (is_string($param)) {
开发者_JAVA百科$types .= 's'; //string
} else {
$types .= 'b'; //blob and unknown
}
}
array_unshift($params, $types);
$query = $this->connection->stmt_init();
if($query->prepare($sql)) {
call_user_func_array(array($query,'bind_param'),$this->refValues($params));
$query->execute();
if($fetch){ // Only if we want to return an array of results
// Get Metadata
$meta = $query->result_metadata();
$fields = $results = array();
while ($field = $meta->fetch_field()) {
$var = $field->name;
$$var = null;
$fields[$var] = &$$var;
}
call_user_func_array(array($query,'bind_result'),$fields);
while ($query->fetch()){
pr($fields);
$results[] = $fields;
}
}
} else die(printf("Error: %s\n", $this->connection->error.' : '.$this->lastQ));
Most likely you've declared $fields
to be a reference somewhere in your code (explicitly or implicitly). Each array element you append to $results
is actually going to be a copy of that same reference, so each array element points to the same bit of memory in php, which'll happen to be the last row fetched from your query.
I'd suggest doing an unset($fields)
before you do your variable binding/result fetching, which would break the reference setting on the $fields
variable.
Okay, I've worked out a solution. Albeit not a very elegant one, but it works :). I'm just making an array called $fieldNames
and storing the names of the fields being returned via mysql. Then in the fetch()
while loop I'm just looping through the $fieldNames
and setting $results
from $fields[$fieldNames]
. The code below might make more sense than I can make by explaining it!
$fields = $results = array();
while ($field = $meta->fetch_field()) {
$var = $field->name;
$fields[$var] = &$$var;
$fieldNames[] = $var;
}
$fieldCount = count($fieldNames);
call_user_func_array(array($query,'bind_result'),$fields);
$i=0;
while ($query->fetch()){
$key = $arKey ? $fields[$arKey] : $i;
for($l=0;$l<$fieldCount;$l++) $results[$key][$fieldNames[$l]] = $fields[$fieldNames[$l]];
$i++;
}
精彩评论