farban6 Posted July 12, 2011 Share Posted July 12, 2011 Hello all I am following a tutorial on netplus about prepared statements. And I understand it all with the exception of references, the call user func array etc. I made my own test to try and understand the problem and while I can get it to work, I cant understand how it works and whats going on behind the scenes, when its useful to use it, is this good practise, is there a better alternative? Here is the tutorial link http://net.tutsplus.com/tutorials/php/the-problem-with-phps-prepared-statements/ Here is my test <?php $test = array(); $test[] = &$test2['testkey']; print_r($test2); print_r($test); ?> Outputs Array ( [testkey] => ) Array ( [0] => ) Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/ Share on other sites More sharing options...
btherl Posted July 12, 2011 Share Posted July 12, 2011 IMHO, references should be avoided unless there's no other choice, or you have a very good reason to use them. They are as bad as global variables, in that they allow you to modify variables elsewhere in the program without it being obvious that the modification is happening. Unfortunately I can't see that video as I have no speakers here, so I don't know why he is suggesting references. Based on that code I don't see why you would need them. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1241986 Share on other sites More sharing options...
requinix Posted July 12, 2011 Share Posted July 12, 2011 Use code tags when posting output. Outputs Array ( [testkey] => ) Array ( [0] => ) $test2 is some array, and apparently it has some "testkey" key in it. Without a value (null? empty string?). That's all stored in memory somewhere. $test is a blank array, and you create an element (key 0, because it's the first item and you didn't specify a key yourself). Its value is whatever that "testkey" value is, except instead of making a copy of the value this new key points to the same place in memory. Copy: $test2[testkey] => ??? $test[0] => ??? Reference: $test2[testkey] => ??? $test[0] ===========^ So instead of two ???s you have just the one. Make it change and you'll affect both places it's used. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1241994 Share on other sites More sharing options...
farban6 Posted July 12, 2011 Author Share Posted July 12, 2011 Interesting stuff, I didn't realize people thought they are as bad as global variables. Through that tutorial I am planning to build a prepared statement which can accept dynamic number of parameters. And one way as shown in the tutorial was to use references. But after your advice, could there be a different alternatives?. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1241996 Share on other sites More sharing options...
xyph Posted July 12, 2011 Share Posted July 12, 2011 Passing by reference has its uses - function someFunc( &$someVar ) { $someVar .= 'APPENDED'; } Assigning a variable by reference has no REAL value, except maybe trying to hack together two scripts the wrong way. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242009 Share on other sites More sharing options...
btherl Posted July 12, 2011 Share Posted July 12, 2011 Ok I think I'm seeing now why he uses references. References are "transitive", in this sense: $a = &$b; $b = &$c; Now $a, $b and $c are all bound together in the same way. They reference each other. If you change any of them, you change all of them. bind_result() "binds" its arguments by making them references. And because the arguments passed to bind_result with call_user_func_array() are already bound to the $row[$field->name] variables as well, the result is a 3 way reference binding. $row[$field->name] is bound to $parameters[$i] which is bound to whatever bind_result() binds it to. I could be totally wrong here - still can't watch that video until I get home. But that seems like a situation where references are the only solution, and where they are appropriate, in that data isn't going to leak in and out of functions (as long as you are careful). Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242020 Share on other sites More sharing options...
requinix Posted July 12, 2011 Share Posted July 12, 2011 I use references most when converting recursive functions into linear functions. You know, like displaying a hierarchy of some sort. References mean I can hold a reference to something, modify it, and know that the original was also affected. It's also great for relationships. You can track hundreds of relationships without needing copies of everything*. I also haven't seen the video, but it sounds like the exact same thing I've done before, and even with bind_param() and bind_result() too. The problem with those functions is that they require references. This is fine if you call the functions literally. But if you use call_user_func_array() then bind_*() will be referencing the variables that were given by cufa(), which aren't the variables you gave to it (because PHP made copies*). So you use a reference to keep the two tied. But you probably started with some variables already, so you make a reference between the cufa() variables and the ones you already have, thus ending up with three references. $foo = "asd"; // first reference // (actually isn't a reference yet, but it will be) bind($foo); function bind(&$bar /* second reference */) { $args = array(... &$bar ...); // third reference call_user_func_array("mysqli_bind_param", $args); // mysqli_bind_param gets a fourth reference } Here you actually end up with four references: $foo, $bar, $args[?], and whatever variable mysqli_bind_param() got. * PHP is smart about copying versus using references. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242022 Share on other sites More sharing options...
xyph Posted July 12, 2011 Share Posted July 12, 2011 @requinix - Why would you use a reference and not the original variable itself? I don't understand the use of having multiple names pointing to one resource. Why not just use one name? Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242035 Share on other sites More sharing options...
requinix Posted July 13, 2011 Share Posted July 13, 2011 @requinix - Why would you use a reference and not the original variable itself? Because I might want to make a change to something and have it propagated everywhere. Say I have a lookup array in the form $lookup = array( 1 => array("title" => "One", "parent" => null, "children" => array()), 2 => array("title" => "Two", "parent" => /* reference to #3 */, "children" => array()), 3 => array("title" => "Three", "parent" => null, "children" => array(2 => /* reference to #2 */)) ); With that I could jump to any item, regardless of where it was in the hierarchy, and go up or down however I pleased. You can do that just fine with copies, but what if I wanted to modify #2's parent's title? Without references I would have to add an "id" item to each array and use $lookup[$lookup[2]["parent"]["id"]]["title"] = "tres"; With references I could forget that "id" array item and just use $lookup[2]["parent"]["title"] = "tres"; If I tried that without references then #2's parent's title would be changed, but #3's title wouldn't be. Admittedly that doesn't happen very often; normally I do it because that's what the data actually represents and I want to make sure that's mirrored in my code. Probably a better example would be modifying some sort of counter or tally, such as how many children a node has (you go up the tree, decrementing each node's counter, until you hit the top). I don't understand the use of having multiple names pointing to one resource. Why not just use one name? Variable names? Because of function calls. They all use different variables. Maybe I don't get the question. How would you "just use one name"? Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242040 Share on other sites More sharing options...
xyph Posted July 13, 2011 Share Posted July 13, 2011 Ignore the second point. I see how that can be helpful, just something I'd never use. If I wanted to modify the data, I'd keep it in a 2d array. If I wanted to display the data, I'd create a recursive function to group and display the data. I don't see a benefit in storing the child of a child of a child in a complex array. If you want to access the data, you're going to need to use a recursive function regardless of how complex or simple you format it. I suppose if you wanted to grab all the children of a specific set, your example would need a few less recursions to do it. Perhaps I've just never run into a challenge that needed such complex and constant interactions of hierarchical data. I'm going to do a little digging, perhaps I can be proven wrong. You mind helping me through if I post a couple code blocks? Just to make sure I'm doing things correctly. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242046 Share on other sites More sharing options...
btherl Posted July 13, 2011 Share Posted July 13, 2011 Another use for references is like this: $big_array = <some huge array of data>; add_foos($big_array); # add_foos(): Adds a foo to each array element of $big_array, without generating a second copy of the array function add_foos(&$big_array) { foreach ($big_array as $key => $val) { $val['foo'] = 'bar'; $big_array[$key] = $val; } # No return value - parameter $big_array is passed by reference and modified return; } If instead you passed $big_array by value and added the foo elements and returned the modified array, PHP will create a second copy of the entire array. If your array is huge this can double your memory usage. In this case it makes sense to use a single well documented reference. If you're not modifying the array then you don't need to do this, as php won't copy the array unless you modify it. Another example is php's built in sort() functions - these all use references so they can do the sorting without making a copy of the array. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242048 Share on other sites More sharing options...
xyph Posted July 13, 2011 Share Posted July 13, 2011 I understand passing a variable to a function by reference, that makes perfect sense. You're keeping the copy in it's own scope, and as long as you know the function was designed to pass by reference, changes to the variable after the function call make sense. The part I'm confused with is creating a variable by reference (in the same scope). requinix provided a great example when using hierarchical data, but I haven't thought of a situation where I'd use it over just storing the data in 2D. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242054 Share on other sites More sharing options...
btherl Posted July 13, 2011 Share Posted July 13, 2011 I also can't think of any situation where I'd use a reference within a data structure. It would drive me crazy debugging, even if it is useful. Another example of memory saving with references in php's "standard library" is mysql_fetch_array(), which creates the integer and named indexes as references to the same data. So even though the data appears twice when you dump the contents, it is only stored once. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242064 Share on other sites More sharing options...
teynon Posted July 13, 2011 Share Posted July 13, 2011 You don't need variable variables. Everything can be done without them. Oops, thought I saws $$var not &$var :/ Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242066 Share on other sites More sharing options...
farban6 Posted July 13, 2011 Author Share Posted July 13, 2011 The code i have simply copied from the tutorial on the link I provided earlier on in the thread. http://net.tutsplus.com/tutorials/php/the-problem-with-phps-prepared-statements/ function read() { $parameters = array(); $results = array(); $mysql = new mysqli('localhost', 'root', '', 'fry') or die('There was a problem connecting to the database'); $stmt = $mysql->prepare('SELECT * FROM usertest') or die('Problem preparing query'); $stmt->execute(); $meta = $stmt->result_metadata(); while ( $field = $meta->fetch_field() ) { $parameters[] = &$field->name; } print_r($parameters); call_user_func_array(array($stmt, 'bind_result'), $parameters); while ( $stmt->fetch() ) { $x = array(); foreach( $row as $key => $val ) { $x[$key] = $val; } $results[] = $x; } return $results; } $results = read(); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>untitled</title> </head> <body> <?php foreach ($results as $row) : ?> <p> <?php echo $row['user_password']; ?> </p> <?php endforeach; ?> </body> </html> I have learnt a fair bit from all the advice and debate on this thread. The only think that i just cant understand is this code while ( $field = $meta->fetch_field() ) { $parameters[] = &$row[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $parameters); If i simply replaced the $parameters values with this while ( $field = $meta->fetch_field() ) { $parameters[] = &$field->name; } surely this makes the parameters passed by reference yet this outputs Warning: Parameter 1 to mysqli_stmt::bind_result() expected to be a reference, value given in C:\xampp\htdocs\xampp\testing\index.php on line 19 so how is this being passed by value? and how is row getting values assigned to the key? Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242462 Share on other sites More sharing options...
btherl Posted July 14, 2011 Share Posted July 14, 2011 I also don't understand why this happens. Can you do a var_dump() of $parameters before it's passed to bind_result()? If it says they're not references then presumably they're not references, and perhaps php wasn't able to make them references. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242545 Share on other sites More sharing options...
farban6 Posted July 14, 2011 Author Share Posted July 14, 2011 $meta = $stmt->result_metadata(); while ( $field = $meta->fetch_field() ) { $parameters[] = &$field->name; } var_dump($parameters); var dump outputs the last fetched values array(3) { [0]=> string(7) "user_id" [1]=> string(9) "user_name" [2]=> string(13) "user_password" } Warning: Parameter 1 to mysqli_stmt::bind_result() expected to be a reference, value given in C:\xampp\htdocs\xampp\testing\index.php on line 21 No references just values, maybe its because $field is set as a method? I am shooting in the dark a bit here Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242825 Share on other sites More sharing options...
requinix Posted July 14, 2011 Share Posted July 14, 2011 What if you var_dump($parameters) inside the loop? I believe you'll see references there, but only for the field that was just added. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242860 Share on other sites More sharing options...
btherl Posted July 15, 2011 Share Posted July 15, 2011 Is it because $field->name is deallocated after the reference is created? Therefore reverting $parameters[] to a normal variable with refcount 0. Sample script to demonstrate: <?php $foo[0] = 1; $bar[0] = &$foo[0]; var_dump($bar); unset($foo); var_dump($bar); ?> Once $foo is deallocated, $bar[0] is no longer a reference, even though it was previously made to be a reference. Definitely not what I would expect, and another reason to avoid references unless you really need them (and you do need them here it seems). The mistake though was referencing something that doesn't really belong to you - $field->name isn't really yours. If you only reference variables you created and you know the history and future use of, then all should be fine. Quote Link to comment https://forums.phpfreaks.com/topic/241845-i-just-cant-understand-the-concept-of-referencing/#findComment-1242907 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.