1

So I've run into a bit of an issue. I know of a solution but it doesn't seem very clean and I'm wondering if there's a better one.

I'm writing a MySQLi wrapper for running prepared statements. As it's a wrapper and is meant to be reused (dynamic) the amount of columns returned depends on the query and isn't static.

The one solution to this that I've found, and seems is what everyone uses, is call_user_func_array.

It works, but my issue with it is it has me creating an extra array of references that I shouldn't really need in the first place.

For example:

<?php

// Connect, prepare statement, etc.

$stmt->execute();

$fields = $stmt->result_metadata();
$fields = $fields->fetch_fields();

foreach ($fields as $field) {
    // Unnecessary creation of an array.
    $params[] = &$row[$field->name];
}

call_user_func_array(array($stmt, 'bind_result'), $params);

?>

So now I'm creating another array just to get call_user_func_array to pass the parameters by reference because it doesn't adhere to the method definition.

Is there some way to get call_user_func_array to adhere to method / function definitions? Is there a cleaner way of calling a method / function with a variable number of parameters? Or, is there just an overall cleaner and better solution to this issue all together?

I've also run into similar problems when calling bind_param while trying to keep the feature of being able to change the bound parameters and rerunning the statement intact.

On somewhat of a side issue, what exactly is the code below doing.

$row[$field->name] = &$row[$field->name];

It oddly works and doesn't produce any errors, though I don't exactly get how a variable can reference itself. Are there any major differences between that and the former other than the fact I'm not creating another array? Is it better?

Thanks.

EDIT:

This is how I used the Reflection API instead of call_user_fun_array. Any input on my usage of it, performance vs. call_user_func_array, implementation, etc. would be greatly appreciated. I haven't really messed with it before and just about every method is undocumented so I'm not really sure of the proper way to use them.

<?php

foreach ($fields as $field) {
    $row[$field->name] = NULL;
}

$refMethod = new ReflectionMethod($stmt, 'bind_result');
$refMethod->invokeArgs($stmt, $row);

?>

1 Answer 1

2

One way i know of is that you can use the Reflection class's isPassedByReference method.

Here is a solution i came up with after facing that issue for a framework i have had been developing.

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the answer. I played around a little with ReflectionMethod and used that to call bind_result and it looks cleaner. I tried to do some benchmarking and couldn't really come to any conclusion if it was slower or not. (was most likely my method of testing) -- I haven't really played with the Reflection classes at all and most methods are undocumented so that didn't help much. Not sure if there's a better way of using them than how I did. -- Thanks. I'm still interested in other solution if there are any though.
just wondering, which method are undocumented, I looked for some at php.net/ and methods were documented and generally their names are self documenting (at least for playing with)
@mathroc I was more referring to only argument lists being available for everything. I haven't messed with reflection in general so it wasn't really a matter of just trying to interpret PHP's implementation of it for me. -- It's uses to get information about a class and it's methods and parameters is pretty self documented as you said. It was trying to figure out how to use it properly when trying to invoke methods or other such things that wasn't exactly crystal for me. -- It really wasn't too much to figure out. I just wasn't sure if my implementation was the right way to go about it.
@anomareh: does your new reflection implementation work even with arguments passed by reference, if yes and you are getting the expected results then it is fine. I personally used isPassedByReference to check if anything was passed by reference and did the appropirate handling afterwords.
@Sarfraz Yes it works. invokeArgs passes by reference. invoke doesn't however. As far as I can tell isPassedByReference just returns whether or not the parameter was passed by reference. The function call fails if it's not passed by reference so there really isn't a need for me to check if it was passed by reference or not. bind_result only accepts references and will fail otherwise. The function behaves fine if you call it normally. The problem is call_user_func_array ignores the method definition and passes by value even though the method is defined to pass by reference.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.