PHP Bind Statements a tiny get_result() nightmare
Ok here is the long story short, I was hosting a php application in godaddy Linux hosting and all of the sudden my database functions start going insane. I was like whaaa the…. cause i was pretty much sure the application is so small that there is no change anything coulda go bad, nevertheless i was pretty sure about the things i have done… Well a programmer should do what he gotta do right ?, so I start debugging,,
hmmm,
- Lets try changing php versions :’) – Fail
- Lets Try Some adons and plugin for php avilable in linux shared hosting – Fail
- Lets Try Some Error Logs ! – Hey i got something there
“Call to undefined method mysqli_stmt::get_result()” which was well hidden in the page’s folder by our godaddy buddies and Apache, oh thank God.
Well it seems mysqlnd driver is installed but the php isn’t compiled compatible to one, and no wonder it worked pretty much as like it should in my local server (wamp) !.
ok, so we pretty much traced the problem and my client is waiting on diet coke. hmmm now what to do, things will get messy if i should re-start the entire coding (which i hate to my bones but will go for it if there is no other safe option.).
so there must be some way to work around the problem, after some short research and scavenging, got a fix,
And
Solution 1 – it seems i should go for BIND_RESULT & FETCH !
Two Extra functions to get data from memory and push to an array (pointer)
1 2 3 4 5 6 7 8 9 |
function db_bind_array($stmt, &$row) { $md = $stmt->result_metadata(); $params = array(); while($field = $md->fetch_field()) { $params[] = &$row[$field->name]; } return call_user_func_array(array($stmt, 'bind_result'), $params); } |
1 2 3 4 5 6 7 8 9 |
function getResultFix($stmt) { $result = array(); $ret; if ($this->db_bind_array($stmt, $result) !== FALSE) { $ret = $result; } return $ret; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function arrayCopy( array $array ) { $result = array(); foreach( $array as $key => $val ) { if( is_array( $val ) ) { $result[$key] = arrayCopy( $val ); } elseif ( is_object( $val ) ) { $result[$key] = clone $val; } else { $result[$key] = $val; } } return $result; } |
The rest was pretty easy instead of looping around the getResult all i had to do was to call getResultFix to point the iterative values to $row,
Then iterate using fetch() and copy value of array from each iteration to a new array. (It was important as the pointer tends to change values during each iteration and a clone of row should be taken to work around that.)
1 2 3 4 5 6 |
$all_rows=array(); $row=$this->getResultFix($statement); while ($statement->fetch()) { array_push($all_rows, $this->arrayCopy($row)); } $statement->close(); |
Wola ! it was finally over, thankyou internet, thankyou godaddy. !!!!
Another Solution : Panic Mode On – Your system missing mysqlnd Driver ! –
If you are able to install new packages on your (debian/ubuntu based) server install the driver:
sudo apt-get install php5-mysqlnd
and then restart your web server
or if you are using windows find one with mysqlnd pre installed, like wamp server.
Well another long night, with a happy ending. 😀
Something is not quite right. Doing vardumps along the way, by statement fetches 4 records. After passing it through these functions, I get an array of 4 rows. However, each of them contains the last record which was returned from the query.
In the loop above:
$row=$this->getResultFix($statement);
while ($statement->fetch()) {
array_push($all_rows, $this->arrayCopy($row));
}
The getResultFix assigns the row values outside the loop but $row isn’t assigned anything within the loop. Is it because of a callback within call_user_func_array which is updating newly fetched values to $row?
public mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )
Try using fetch parameters
Refer: http://php.net/manual/en/pdostatement.fetch.php
Something is definitely odd.
var_dump($row) within the while loop shows the the values being pushed are: rec1, rec2, rec3, rec4.
var_dump($all_rows) immediately after that loop shows: rec4, rec4, rec4, rec4