#43568 [Opn]: mysqli statement stmt->bind_param doesn't work when called by call_user_func

From: Date: Fri, 04 Jan 2008 17:20:09 +0000
Subject: #43568 [Opn]: mysqli statement stmt->bind_param doesn't work when called by call_user_func
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-121038@lists.php.net to get a copy of this message
ID: 43568 User updated by: gabriel at oxeva dot fr Reported By: gabriel at oxeva dot fr Status: Open Bug Type: MySQLi related Operating System: Linux 2.6 PHP Version: 5.3CVS-2007-12-11 (snap) New Comment: It seems you posted your comment before I finished writing mine. Good to see that I'm not going crazy because I just tested the case with sort and got the same bug as you! Should I change the category for this bug? If so, which one? Previous Comments: ------------------------------------------------------------------------ [2008-01-04 14:53:32] gabriel at oxeva dot fr I understand now why this isn't supposed to work, but it is with PHP 5.2 This "new" behavior make this bind_param function a lot less attractive when using it in situations like ZF does: binding an unknown number of parameters to a statement (like in any Object-Relational Mapper). There is no way now other than using the very ugly eval() to dynamically create the required number of variables to bind with bind_param. Besides, this method is never suppposed to return NULL, (doc says boolean return, TRUE on success, FALSE on failure). This is why I almost immediately thought that was a bug. Another fact is the doc example is very strange with calling stmt_bind_param with variables _before_ having them created. This is very "special" coding style. My final thought: The old behavior (PHP 5.2) is really useful because there is no other way to do the same with the new one except using eval() as an ugly workaround, and the new behavior is returning an undocumented (and useless) value. I really don't know if I have to file a new bug report in 5_2 about the incorrect behavior of bind_param (which is IMHO the most useful one). Thank you anyway for the explanation, I'm now waiting for the final opinions about this. ------------------------------------------------------------------------ [2008-01-04 14:30:39] uw@php.net Hold on, a PHP internals expert should have a look. sort() is another example of a function which uses pass by reference. The manual says about call_user_func_array(): "Note: Referenced variables in param_arr are passed to the function by a reference, others are passed by a value. In other words, it does not depend on the function signature whether the parameter is passed by a value or by a reference. " From a discussion with Johannes: sapi/cli/php -r '$a = array(2, 1); var_dump(call_user_func_array("sort", array($a)));' PHP 5.2 -> bool(true) PHP 5.3 -> NULL Looks like its not a mysqli issue but rather a general PHP issue. ------------------------------------------------------------------------ [2008-01-04 13:49:02] uw@php.net Forgot to say: IMHO this should be reported over at Zend Framework but not here. I've tested 5_2, 5_3, 6_0 and I see no differences in handling. ------------------------------------------------------------------------ [2008-01-04 13:42:14] uw@php.net IMHO this is not a bug. However, I leave it to Johannes/Andrey to review and close the issue. bind_param() is about binding variables not constant values: "stmt->bind_param() — Binds variables to a prepared statement as parameters". The signature of the function tells you that you have to pass input parameter variables by reference: bool mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1 [, mixed &$... ] ) Using references to "real variables" instead of "constant values" does work fine. Note the small difference between references to variables in PHP and memory pointer in C. In PHP your references have to point to existing variables. You can't make them point to arbitrary places in memory like in C. If a PHP function asks you to provide a reference to an existing variable, you must not try to pass a (constant) value to it. But this is exactly what you do in your call_user_func_array() example. Use the function like this: $int = 1; mysqli_stmt_bind_param($stmt, 'i', $int); $stmt->bind_param('i', $int); And, if you want to use call_user_func_array(), the syntax is: $int = 1; $format = 'i'; $params = array(0 => $format, 1 => &$int); call_user_func_array('mysqli_stmt_bind_param', $params); call_user_func_array(array($stmt, 'bind_param'), $params); // - or - $int = 1; $params = array(0 => 'i', 1 => &$int); call_user_func_array('mysqli_stmt_bind_param', $params); call_user_func_array(array($stmt, 'bind_param'), $params); // - or - $int = 1; call_user_func_array('mysqli_stmt_bind_param', array('i', &$int)); Neither of the following does work with PHP 5_3. Recall that the function is about binding variables not binding (constant) values, recall that you have to pass a reference to a variable: WRONG: mysqli_stmt_bind_param($stmt, 'i', 1); WRONG: call_user_func_array('mysqli_stmt_bind_param', array('i', 1)); ------------------------------------------------------------------------ [2007-12-11 17:11:46] gabriel at oxeva dot fr Description: ------------ The Mysqli method stmt->bind_param() doesn't work when called by call_user_func_array. Too bad Zend Framework is using this method with the Mysqli driver. In the following example, call_user_func_array always return NULL, but directly calling $stmt->bind_param() works and return the correct bool(true) value. Note: this works in PHP 5.2 Note: The same error occurs using either libmysqlclient or mysqlnd. Final note: ATM the PDO_mysql driver works. But leaving a bug like this in the mysqli driver is not an option :-) Reproduce code: --------------- $my = new mysqli('localhost', 'test', 'test', 'testdb'); $stmt = $my->prepare('INSERT INTO car (brand, brand_id, car_type) VALUES (?, ?, ?)'); $param = array('sss', 'GMC', 1, 'SUV'); $return = call_user_func_array(array($stmt, 'bind_param'), $param); var_dump($return); $stmt->execute(); echo $stmt->errno, ':', $stmt->error; Expected result: ---------------- var_dump($return) prints bool(true) No error returned in $stmt->errno / $stmt->error Actual result: -------------- var_dump($return) prints NULL Statement error is returned: 2031:No data supplied for parameters in prepared statement ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=43568&edit=1

« previous php.bugs (#121038) next »