Dynamically creating bind_result

In a pagination class, I use it for multiple query sets. The bind_result code as follows works fine to populate an array with the result set.

$prep1->bind_result($venueid, $name, $address, $city, $state, $zipcode);
$x = 0;
while ($prep1->fetch())
{
$users[$x][0] = $venueid;
$users[$x][1] = $name;
$users[$x][2] = $address;
$users[$x][3] = $city;
$users[$x][4] = $state;
$users[$x][5] = $zipcode;
$x++;
}

What I would like to be able to do is pass in an array of field names and dynamically create the bind_result statement (which I would assume can be done using call_user_func_array with an array of field names starting with $. But I still need to reference those names in the while statement to populate my array. Even with $$ all I get is a literal so it is interpreting it as a string, not a field name from the result set.

It is my understanding that in order to retrieve the result set from a prepared statement I need to bind column names and then do a fetch, so I am not allowed to process the results with a numeric array, is that correct?

$fnamew[$i] =& $$fname[$i];

Take a look at the first comment on manual page here:

http://www.php.net/manual/en/mysqli-stmt.bind-result.php

Assuming that is what your doing it should work.

Update;

I have half of it working but can’t get the bind_result to dynamically build.
For the fetch part, this code works fine where numcols is the number of elements in the field array and fname is the field array:

$y = 0;
while ($prep1->fetch())
{
for ($x = 0; $x < ($numcols); $x++)
{
$users[$y][$x] = ${$fname[$x]};
}
$y++;
}

I tried this code for the bind_result both with and without the $ signs in front of the field names.

for ($i = 0; $i < $numcols; $i++)
{
$fnamew[$i] = “$” . $fname[$i];
}
call_user_func_array(array($prep1, ‘bind_result’), $fnamew);

I had the same sort of problems with bind_param a few months ago.

I have a bad feeling that the situation with prepared statements and call_user_func_array needing references is going to have people inadvertently creating bugs in their applications based on references, or worse yet, security holes that are a nightmare to track down.

Be careful. :slight_smile:

Understand. So is there a way to take an array of strings and turn them into variable names using ${}? I think I tried every possible combination but certainly could have missed one. :slight_smile:

Actually I got it to create them as variables in the array but when you dump the array all you see is “” because that’s the value of the variable I am assuming.

And if the values in the array are “$fldnm” it doesn’t recognize those as variable names. The “” are added by the variable dump, not by me on creation.

Anyhow, time to move on unless someone comes up with a way. Thanks again for all your input and the discussion.

I understand the loop issue and I think I understand your point with the bind_result and bind_param generation of variable names but will spend some more time with this to make sure.

And you make a very good point that there is the possiblity for problems here if you are not careful and your input there is most valuable. I will be careful in how the names are used and where all this is used.

Thanks again for the discussion.

The trouble would come from the fact that bind_param and friends expect to recieve arguments by reference and that the list of variable names that will be referenced is determined at runtime.

Bugs could arise if any of the variable names are generated, rather than pulled from a hard-coded list. Especially if the generation has any sort of user input as generation input.

By bugs, I mean that previously created variables could be overwritten by bind_result and unexpected variables could inadvertently be pulled into a query by bind_param.

For an example of an overwrite bug, check out this pair of loops

for($i = 0; $i < 100; $i++)
{
	for($i = 0; $i < 50; $i++)
	{
	
	}
}

Because the inner loop keeps resetting $i, the loop would run indefinitely. While a bind_result bug probably wouldn’t leave anything running in an infinite loop, it might overwrite something that’s used to build a later variable and cause unexpected output.

One more note, I am only using the dynamic bind_param for the WHERE or JOIN ON clause in select statements. Any direct manipulation of the database is done in long hand.

Would you expound on that a little bit. :o

My bind_param statement is

call_user_func_array(array($prep1, ‘bind_param’), $bind_param);

with the $bind_param passing an array of values, i.e. strings and integers with the [0] element being a string “sssii” for example. Where would the trouble arise?

Great! That works. Thanks for the input.

So in the bind_param, I am unpacking values, not actual variable names? I tried passing them, or at least I think I did, as ${fname1} which should assign them as variable names, right? Anyhow, if you happen to think of anything else that might work let me know but it’s not that critical. It’s a relatively easy workaround for that particular piece.

Well the issue is that call_user_func_array() will not unpack the array and pass the variables by reference. It is passing copies not references.

Thanks, I’ll give it a try. I thought what I was doing would work and was able to do it with bind_param so I was surprised when it didn’t work with bind_result. The messiest part of it in any event is the while loop and I was able to get that one at least. Thanks again for the input.

The issue is passing the variables by reference. From what I recall I don’t think this possible. I vaguely remember attempting what your trying to do a long while back and falling short without eval. One thing you could try is to override bind_result accepting an array by reference. Than looping through it and calling parent::bind_result() to bind the reference. That may work though never tried it. You can do it with eval though if you build out the string and eval it but its pretty dirty that way.