ID: 43568
Updated by: [EMAIL PROTECTED]
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:
I suggest that we leave the bug status as is for the moment. From what
I know some PHP hackers are already discussing the case and Johannes
(Schlüter) will take care that it does not get forgotten.
Your comment on the example in the documentation is welcome. I agree
with you that, for example, a code comment might be help beginners
understand the example better.
The manual example works because PHP implicitly creates a variable for
you whenever you start to use one. There's no need in PHP to sort of
declare a variable before you use it. So, on the one hand it might make
sense to change the example like this:
$bind_param = null;
mysqli_stmt_bind_param(..., &$bind_param)
... on the other hand, there's no need for the assignment operation.
Its a PHP feature that you can start using variables ad-hoc and PHP does
all the magic for you behind the scenes to make this possible. In that
sense the extra line is nothing but overhead.
A beginner might appreciate to see the line '$bind_param = null' before
the call to mysqli_stmt_bind_param() to sort of better visualize the
"pass by reference" requirement but an experienced PHP hacker might
remove the line from the code because its not needed.
Maybe the bottom line is to write even more "verbose" examples?
Previous Comments:
------------------------------------------------------------------------
[2008-01-04 17:20:09] gabriel at oxeva dot fr
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?
------------------------------------------------------------------------
[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] [EMAIL PROTECTED]
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] [EMAIL PROTECTED]
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] [EMAIL PROTECTED]
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));
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/43568
--
Edit this bug report at http://bugs.php.net/?id=43568&edit=1