3

I've been doing a lot of Objective-C programming lately, and now that I'm coming back to PHP, I have to be honest, I miss the named parameters (at first I hated them, now I love them, go figure).

Anyway, in PHP, I sometimes see people passing arrays to functions as a pseudo way of naming parameters (with the added benefit of not having to worry about the order), but sometimes that makes function writing over-complicated. Also, sometimes I want to call the function with named parameters, but sometimes it's easier and faster not to.

Does anyone simply do something like this:

function calculateArea( $width, $height ) {
    // do calculations here...
}

// and then call the function like so:
calculateArea( $width = 10, $height = 5 );

It seems to work fine, at least with my version of PHP, and I'm wondering if other people use this technique as a workaround for named parameters as well. I'm also wondering if anyone knows of some compelling reasons why I shouldn't be doing this.

Thanks!

UPDATE:

Thanks for all the quick responses everyone. To make things more clear, let me just say that I understand that passing an associative array is a better option in most scenarios, but sometimes you're working with functions that you've already written and you don't want to change how their called in every single part of your code. Also sometimes you're working with a secondary framework and you don't have any control over how the function was written.

If I'm looking at code I wrote a year ago and I see: echo $zc->expand('Foo', 'Bar', 10, 1, 0, null, null, array('class'=>'code'), false);, that's not very helpful.

So, to reword my question, I'm basically asking this:
Sometimes passing arguments to a function via assignment is easier to read. What are the downsides of doing this, and will it work in all versions of PHP?

Philip Walton
  • 29,693
  • 16
  • 60
  • 84
  • 2
    why not simply `calculateArea( 10, 5 );` ? – tereško Apr 30 '11 at 18:28
  • @ teresko I actually wanted to say the same thing. @Philip your question is not clear, what exactly are you asking ? – Khez Apr 30 '11 at 18:30
  • 1
    It should work fine in all versions of PHP, but is it what you want? To define `$width` and `$height` outside the function scope? PHP's arguments don't work like Python's: `doSomething(width=10, height=5)`. That would be something like `doSomething(array('width'=>10, height=>5))` in PHP. – Rudie Apr 30 '11 at 18:32
  • @Rudie he's not defining them outside the function scope. He is setting and passing variables to the function. Variables he probably won't need again in the current scope. He's effectively creating a memory leak if you want to be technical. – Khez Apr 30 '11 at 18:33
  • It does work, but it does not actually use [named parameters](http://stackoverflow.com/questions/1342908/named-php-optional-arguments) in current PHP versions. But as long as you are aware of the side-effects on the local scope, this can aid readability (for lengthy parameter lists). But it's rather uncommon. – mario Apr 30 '11 at 18:34
  • He's defining them outside the function scope... Maybe useless, maybe that's exactly what he wants. But they will be available (defined) after calculating the area, in the scope of where the function is called. – Rudie Apr 30 '11 at 18:35
  • @Khez What he's asking if they will be named arguments (like in my above Python example). @Philip They won't be. – Rudie Apr 30 '11 at 18:36
  • @Rudie he actually called them psuedo named parameters, so he knows they're not. Philip's entire reasoning is to simply have a more readable passing of parameters for functions that require more than one parameter. – Anther Apr 30 '11 at 18:48
  • I think we're all on the same page here... It doesn't work the way he would want. But the variables WILL be defined in the scope where the function is called. Wanna bet? http://www.ideone.com/VOSH3 – Rudie Apr 30 '11 at 18:53
  • If you can't remember the order of a functions parameters, you should use an IDE an the appropriate auto-complete-feature… – feeela Apr 30 '11 at 19:06
  • See PHP8's new feature: https://stackoverflow.com/a/64997399/2943403 – mickmackusa Aug 03 '21 at 23:51

5 Answers5

4

With using calculateArea( $width = 10, $height = 5 ) you are not specifying the parameters by their names as you can do in other languages like Python.

Instead $width = 10 and $height = 5 in the function call are just two variable assignment expressions.

The reason for that this still works as expected is that an assignment expression does not just assign the value but it also returns the assigned value:

The value of an assignment expression is the value assigned. That is, the value of "$a = 3" is 3.

Thus, effectively calculateArea( $width = 10, $height = 5 ) is calling calculateArea with the same parameters as calculateArea(10, 5) does but it also assigns two variables:

calculateArea( $width = 10, $height = 5 );
var_dump($width);   // int(10)
var_dump($height);  // int(5)
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • @Khez It's not really that big of a leak if the variables are contained within a function somewhere. If he's dealing with a whole bunch of global variables that are potentially getting overwritten then I'm really sure the need for passing the arguments as "named variables" has become very apparent :P. – Anther Apr 30 '11 at 18:42
  • Is it really that big of a memory leak? Wouldn't it be exactly the same as if you'd assigned those values to the variables outside of the function call? – Philip Walton Apr 30 '11 at 19:09
  • @Philip Walton: It isn’t a memory leak at all. And you’re not passing parameters or variables but only values. The parameter variables inside the function are only used to address the values somehow. Other languages use other concepts (like JavaScript that uses [`arguments`](https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments) for the actual arguments). – Gumbo Apr 30 '11 at 19:24
4

I think this is a bad idea from the perspective that you don't have any safety if you get the order wrong. Using a map is a much safer way of emulating this. You also have the side effect of setting the values of these variables in the local scope, which may or may not be an issue.

calculateArea( $height = 5, $width = 10 ); # oops!

function calculateArea( $width, $height ) {
    // do calculations here...
}

With a array (map), it doesn't matter what order you put them in.

calculateArea( array( 'height' => 5, 'width' => 10 ) ) # yea!

function calculateArea( $dimensions ) {
    $width = $dimensions['width'];
    $height = $dimensions['height'];
}
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 2
    I'd be a much bigger fan if you perpetuated great variable names by actually naming `$params` `#dimensions`, as a lot of newer programmers will see this and create every function requiring an array named `$params`... I'm just saying this because of how explicit the example is, I feel that the coding style in examples and solutions should match that explicitness. – Anther Apr 30 '11 at 18:44
  • this is an excellent answer, but unfortunately not really what I was asking. I've updated my question to make it more clear. – Philip Walton Apr 30 '11 at 19:17
  • @Philip - you asked for a compelling reason not to do it. I answered that question: you're providing yourself with a false sense of security and, eventually, some pernicious bug. If you don't use the map, it's better IMO not to use the "named" parameters because it can fool you into thinking the call is correct when it isn't. That's especially true if you're moving between languages. Leaving them out *forces* you to check the function definition and make sure that your call matches. I'd say refactor to a map (if you like named parameters) when you can, omit the names when you can't. – tvanfosson Apr 30 '11 at 19:21
2

You should not use variable assignments in function calls because it's likely to cause unexpected results. calculateArea($a = 10, $b = 5) also works. After that function call is completed, $a === 10 and $b === 5. If these variables had different values before the function call, those values are overridden.

Arjan
  • 9,784
  • 1
  • 31
  • 41
0

You can call your function in any of these ways:

calculateArea(10,5);

or this:

calculateArea($width,$height);

or this:

calculateArea($xvar,5);

But assigning values inside the function call is usually bad practice. It's technically correct, but makes the code hard to read. Instead of doing this:

calculateArea( $width = 10, $height = 5 );

Do this:

$width = 10;
$height = 5;
calculateArea( $width, $height );

Or this:

$width = 10;
$height = 5;
calculateArea( 10, 5 );

They all have the same effect, but declaring the variables outside the function makes it clear what their scope is.

Benubird
  • 18,551
  • 27
  • 90
  • 141
0

Well, now you know, that PHP hasn't this feature. But I want to say, that passing array is a bad way too. In this way, you have to keep in memory (or in phddoc comment in best case), which keys can be used in array, you can't set 'default value', and you can easy make typo in name of array's key.
So I prefer to use objects for this cases (since PHP hasn't 'structures' too). In object you can set default values, you can set type of needed object in function declaration, and in IDE you can get code-complete for object's fields names. As example:

class DimensionsParams
{
    public $width = 5;
    public $height;
}

function calculateArea(DimensionsParams $params)
{
    // do calculations here...
    return $params->height*$params->width;
}

Of course, it's not best choice for each function, but it's best variant for 'named parameters' (in my opinion).

OZ_
  • 12,492
  • 7
  • 50
  • 68