views:

1133

answers:

10

Let's say I've got a PHP function foo:

function foo($firstName = 'john', $lastName = 'doe') {
    echo $firstName . " " . $lastName;
}
// foo(); --> john doe

Is there any way to specify only the second optional parameter?

Example:

foo($lastName='smith'); // output: john smith
+3  A: 

No. The usual way of doing this is with some heuristics to determine which parameter was implied, like string length, typing, etc.

Generally speaking, you'd write the function to take the parameters in the order of most required to least required.

Ryan Graham
+2  A: 

The way you want: no.

You could use some special mark, like NULL to note that value is not supplied:

function foo($firstName, $lastName = 'doe') {
    if (is_null($firstName))
        $firstName = 'john';
    echo $firstName . " " . $lastName;
}

foo(null, 'smith');
Milan Babuškov
+9  A: 

PHP does not support named parameters for functions per se. However, there are some ways to get around this:

  1. Use an array as the only argument for the function. Then you can pull values from the array. This allows for using named arguments in the array.
  2. If you want to allow optional number of arguments depending on context, then you can use func_num_args and func_get_args rather than specifying the valid parameters in the function definition. Then based on number of arguments, string lengths, etc you can determine what to do.
  3. Pass a null value to any argument you don't want to specify. Not really getting around it, but it works.
  4. If you're working in an object context, then you can use the magic method __call() to handle these types of requests so that you can route to private methods based on what arguments have been passed.
Noah Goodrich
+3  A: 

If you have multiple optional parameters, one solution is to pass a single parameter that is a hash-array:

function foo(array $params = array()) {
    echo $params['firstName'] . " " . $params['lastName'];
}

foo(array('lastName'=>'smith'));

Of course in this solution there's no validation that the fields of the hash array are present, or spelled correctly. It's all up to you to validate.

Bill Karwin
Darn it, you just beat me to it!
Teifion
A: 

No there isn't but you could use an array:

function foo ($nameArray) {
    // Work out which values are missing?
    echo $nameArray['firstName'] . " " . $nameArray['lastName'];
}

foo(array('lastName'=>'smith'));
Teifion
Unset variable!!
Darryl Hein
need => not =
Kent Fredric
Whoops! I've not coded PHP for a few weeks, been using too much Python.
Teifion
A: 

Sadly what you're trying to do has no "syntactic sugar" way of doing it. They're all varying forms of WTF.

If you need a function that takes an undefined number of arbitrary parameters,

function foo () { 
     $args = func_get_args(); 
     # $args = arguments in order 
}

Will do the trick. Try avoid using it too much, because for Php this is a bit on the magical side.

You could then optionally apply defaults and do strange things based on parameter count.

function foo(){ 
   $args = func_get_args();
   if( count($args) < 1 ){ 
       return "John Smith"; 
   }
   if( count($args) < 2 ) { 
       return "John " .$args[0];
   }
   return $args[0] . " " . $args[1];
}

Also, you could optionally emulate Perl style parameters,

function params_collect( $arglist ){ 
    $config = array();
    for( $i = 0; $i < count($arglist); $i+=2 ){ 
       $config[$i] = $config[$i+1];
    }
    return $config; 
}
function param_default( $config, $param, $default ){ 
    if( !isset( $config[$param] ) ){ 
           $config[$param] = $default;
    }
    return $config;
}

function foo(){ 
   $args = func_get_args();
   $config = params_collect( $args ); 
   $config = param_default( $config, 'firstname' , 'John' ); 
   $config = param_default( $config, 'lastname' ,  'Smith' ); 
   return $config['firstname'] . '  ' . $config['lastname'];   
}

foo( 'firstname' , 'john', 'lastname' , 'bob' ); 
foo( 'lastname' , 'bob', 'firstname', 'bob' ); 
foo( 'firstname' , 'smith'); 
foo( 'lastname', 'john' );

Of course, it would be easier to use an array argument here, but you're permitted to have choice ( even bad ways ) of doing things.

notedly, this is nicer in Perl because you can do just foo( firstname => 'john' );

Kent Fredric
Note to self: applying Perl logic to PHP makes things go bang. Stick with Perl and never look back.
Kent Fredric
+5  A: 

A variation on the array technique that allows for easier setting of default values:

function foo($arguments) {
  $defaults = array(
    'firstName' => 'john',
    'lastName' => 'doe',
  );

  $arguments = array_merge($defaults, $arguments);

  echo $arguments['firstName'] . ' ' . $arguments['lastName'];
}

Usage:

foo(array('lastName' => 'smith')); // output: john smith
ceejayoz
This $defaults and array_merge boilerplate is all over my PHP code. +1
gnud
A: 

You could refactor your code slightly:

function foo($firstName = NULL, $lastName = NULL)
{
    if (is_null($firstName))
    {
        $firstName = 'john';
    }
    if (is_null($lastName ))
    {
        $lastName = 'doe';
    }

    echo $firstName . " " . $lastName;
}

foo(); // john doe
foo('bill'); // bill doe
foo(NULL,smith); // john smith
foo('bill','smith'); // bill smith
Andrew G. Johnson
A: 

yeah, this moment is a one of php lacks. perhaps, the best way is to use array -- better approach, i don't see:(

A: 

I found this constructor in the WP_Widget class of the new WordPress release:

function __construct( $id_base = false, $name, $widget_options = array(), $control_options = array() )

$name is not optional so to make $id_base optional is senseless, isn't it?