3

I wrote a function that is supposed to take some variables and then change the value of those variables. However, after running the function, the variables remained unchanged. Then I did some googling and discovered you need to put an & in front of variable names. The code then did what I wanted it to do. However, I don't understand why you would need to put an &. Is there some other way to accomplish what I needed to do? Basically I'm confused with the notion of passing by reference. This is where my woes start, LOL:

In all the languages I’ve learned so far (python, java, ruby), the parameters that a function would take would change the value of the variables as instructed in the algorithm without any passing by reference, a concept that I've just discovered in PHP. Why has PHP chosen to do this? Could you please explain the logic behind references? Finally, there's people all over the web who are saying: Don't use references? If not, how else do I get to my solution. Then there's also deprecations in for references in PHP... Sorry it's a jumble.

I went through the PHP Manual for references but I found it pretty hard to digest.

Here's some code that I added the & sign to:

<?php

$comments = "";
$airline_name = "United";
$flight_number = "262";
$departure_airport = "";

function airport(&$one, &$two, &$three, &$four) {
   if ( !empty($one) || !empty($two) || !empty($three) ) {
         $one = !empty($one) ? "Airline Name: $one<br>" :"Airline Name: PLEASE PROVIDE AIRLINE NAME<br>";
         $two = !empty($two) ? "Flight Number: $two<br>" : "Flight Number: PLEASE PROVIDE FLIGHT NUMBER<br>";
         $three = !empty($three) ? "Departure Airport: $three<br>" : "Departure Airport: PLEASE PROVIDE DEPARTURE AIRPORT<br>";
         $four = !empty($four) ? "Comments: $four<br>" : "";
   }

}

airport($airline_name,$flight_number,$departure_airport,$comments);

echo $airline_name,$flight_number,$departure_airport,$comments;

?>
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Govind Rai
  • 14,406
  • 9
  • 72
  • 83
  • 3
    That's a poor programming practice. Pass values in, get new values. That's much more maintainable and safer. – John Conde Dec 24 '15 at 20:19
  • 2
    http://stackoverflow.com/questions/2157799/when-to-pass-by-reference-in-php --- http://stackoverflow.com/questions/11360810/php-pass-by-reference-confusion and question is, *why?* – Funk Forty Niner Dec 24 '15 at 20:20
  • If the function returns the new values as an array you can do `list($var1,$var2) = myFunc()` – MDEV Dec 24 '15 at 20:21
  • 2
    "In all the languages I’ve learned so far, I’ve never had to explicitly pass arguments for the functions to modify the variables." Which are those? – Axalix Dec 24 '15 at 20:22
  • By default, arguments in C++ are passed by value - `void foo(int y)`; to pass by reference you use `void foo(int &y)`, or to pass by pointer you use `void foo(int *y)`.... there's one other language that does it the same way – Mark Baker Dec 24 '15 at 20:23
  • Java is always pass by value for primitives, pass by reference for objects; Ruby is always pass by reference; with Python, it depends whether the variable is mutable or immutable – Mark Baker Dec 24 '15 at 20:25
  • Probably JavaScript (w/o passing a variable): `` – Axalix Dec 24 '15 at 20:27
  • @JohnConde so your saying passing by reference is a poor programming practice? Could you further elaborate what you mean by pass values in, get new values? – Govind Rai Dec 24 '15 at 20:31
  • @Axalix I've reworded my question. What I meant by that is when I've defined functions in Java and Python and Ruby, I've never had to do anything special like add an `&` before the parameter. – Govind Rai Dec 24 '15 at 20:32
  • @GovindRai, check this: https://en.wikipedia.org/wiki/Evaluation_strategy – Axalix Dec 24 '15 at 20:34
  • In Ruby, everything is an object. If you pass an object in PHP, it is the same: you can (must) skip "&" as well `f($object)`. – Axalix Dec 24 '15 at 20:40
  • Object Oriented Programming 101 – CodeGodie Dec 24 '15 at 20:42
  • *"after running the function, the variables remained unchanged."* - I don't understand. I ran that function from your other question/answer, so there's something you're leaving out here. Again, *"why?"* – Funk Forty Niner Dec 24 '15 at 20:55

1 Answers1

4

The reason that some other languages do not need to do this, is because they use objects: altering the state of an object is reflected to all references pointing to that object. If however you pass a primitive type in Java (like int) and you alter the parameter, the value will not be altered. The same story is for Strings since you cannot modify their state, you can only modify the reference passed as an argument. Note it is still pass-by-value, since you copy the reference which is basically what your method holds for an object.

PHP passes a string by value, which means - at least conceptually - a copy of the string is made before calling it.

Nevertheless pass-by-reference is sometimes considered dangerous. It is a concept that is used in C and C++ (and even in C#) but programming languages like Java do not allow this. You better use output to enable modifications of variables since it makes it syntactically explicit:

function airport($one,$two,$three,$four) {
    if (!empty($one) || !empty($two) || !empty($three) ) {
        $one = !empty($one) ? "Airline Name: $one<br>" :"Airline Name: PLEASE PROVIDE AIRLINE NAME<br>";
        $two = !empty($two) ? "Flight Number: $two<br>" : "Flight Number: PLEASE PROVIDE FLIGHT NUMBER<br>";
        $three = !empty($three) ? "Departure Airport: $three<br>" : "Departure Airport: PLEASE PROVIDE DEPARTURE AIRPORT<br>";
        $four = !empty($four) ? "Comments: $four<br>" : "";
    }
    return array($one,$two,$three,$four);
}

and call it with:

list($airline_name,$flight_number,$departure_airport,$comments) = airport($airline_name,$flight_number,$departure_airport,$comments);

list is a special function where you call the variables by reference (yes, you do, it is actually a language construct as stated in the manual). The point is when you assign an array to a list construct, the elements in the array are assigned element-wise to the variables specified in the list. For example (taken from here):

list($drink, $color, $power) = array('coffee', 'brown', 'caffeine');

is equivalent to:

$drink = 'coffee';
$color = 'brown';
$power = 'caffeine';

it is thus more or less the opposite of array: you split the array into elements and perform element-wise assignment.


Using list, it is clear to everyone these variables will change. Furthermore you do not have to look into the function signature to know whether a variable will change: it won't. If you change your mind and want to set other variables, that's easy as well.

Govind Rai
  • 14,406
  • 9
  • 72
  • 83
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Thanks! Could you further explain the code in your answer? So you end up returning an array and then what exactly are you doing when you set the list? I've never seen that before. – Govind Rai Dec 24 '15 at 20:54
  • 1
    "The reason that some other languages do not need to do this, is because they use objects: altering the state of an object is reflected to all references pointing to that object." The exact same thing is true for objects in PHP 5+. – newacct Dec 25 '15 at 07:58
  • 1
    "If however you pass a primitive type in Java (like int) and you alter the parameter, the value will not be altered." Actually, this is true no matter what type is passed. The thing passed will not be altered. Note that objects cannot be passed because "objects" are not values -- there are no "object types". The only types in Java are primitive types and reference types. Same is true in PHP 5+ -- "objects" are not values, you can only deal with object references. – newacct Dec 25 '15 at 08:00
  • @newacct: that's more or less what I've wanted to make clear. Since you can only alter either the reference to an object, or tha value. But this changes will not be reflected on the caller. – Willem Van Onsem Dec 25 '15 at 09:39