named PHP optional arguments?

百般思念 提交于 2019-11-26 06:46:57

问题


Is it possible in PHP 4/5 to specify a named optional parameter when calling, skipping the ones you don\'t want to specify (like in python) ?

Something like:

function foo($a,$b=\'\', $c=\'\') {
    // whatever
}


foo(\"hello\", $c=\"bar\"); // we want $b as the default, but specify $c

Thanks


回答1:


No, it is not possible : if you want to pass the third parameter, you have to pass the second one. And named parameters are not possible either.


A "solution" would be to use only one parameter, an array, and always pass it... But don't always define everything in it.

For instance :

function foo($params) {
    var_dump($params);
}

And calling it this way :

foo(array(
    'a' => 'hello',
));

foo(array(
    'a' => 'hello',
    'c' => 'glop',
));

foo(array(
    'a' => 'hello',
    'test' => 'another one',
));

Will get you this output :

array
  'a' => string 'hello' (length=5)

array
  'a' => string 'hello' (length=5)
  'c' => string 'glop' (length=4)

array
  'a' => string 'hello' (length=5)
  'test' => string 'another one' (length=11)

But I don't really like this solution :

  • You will lose the phpdoc
  • Your IDE will not be able to provide any hint anymore... Which is bad

So I'd go with this only in very specific cases -- for functions with lots of optionnal parameters, for instance...




回答2:


No, PHP cannot pass arguments by name.

If you have a function that takes a lot of arguments and all of them have default values you can consider making the function accept an array of arguments instead:

function test (array $args) {
    $defaults = array('a' => '', 'b' => '', 'c' => '');
    $args = array_merge($defaults, array_intersect_key($args, $defaults));

    list($a, $b, $c) = array_values($args);
    // an alternative to list(): extract($args);

    // you can now use $a, $b, $c       
}

See it in action.




回答3:


No, it isn't.

The only way you can somewhat do that is by using arrays with named keys and what not.




回答4:


As of PHP 5.4 you have shorthand array syntax (not nessecary to specify arrays with cumbersome "array" and instead use "[]").

You can mimic named parameters in many ways, one good and simple way might be:

bar('one', ['a1' => 'two', 'bar' => 'three', 'foo' => 'four']);
// output: twothreefour

function bar ($a1, $kwargs = ['bar' => null, 'foo' => null]) {
    extract($kwargs);
    echo $a1;
    echo $bar;
    echo $foo;
}



回答5:


With PHP, the order of arguments is what matters. You can't specify a particular argument out of place, but instead, you can skip arguments by passing a NULL, as long as you don't mind the value in your function having a NULL value.

foo("hello", NULL, "bar");



回答6:


It's not exactly pretty, but it does the trick, some might say.

class NamedArguments {

    static function init($args) {
        $assoc = reset($args);
        if (is_array($assoc)) {
            $diff = array_diff(array_keys($assoc), array_keys($args));
            if (empty($diff)) return $assoc;
            trigger_error('Invalid parameters: '.join(',',$diff), E_USER_ERROR);
        }
        return array();
    }

}

class Test {

    public static function foobar($required, $optional1 = '', $optional2 = '') {
        extract(NamedArguments::init(get_defined_vars()));
        printf("required: %s, optional1: %s, optional2: %s\n", $required, $optional1, $optional2);
    }

}

Test::foobar("required", "optional1", "optional2");
Test::foobar(array(
    'required' => 'required', 
    'optional1' => 'optional1', 
    'optional2' => 'optional2'
    ));



回答7:


You can keep the phpdoc and the ability to set defaults by passing an object instead of an array, e.g.

class FooOptions {
  $opt1 = 'x';
  $opt2 = 'y';
  /* etc */
};

That also lets you do strict type checking in your function call, if you want to:

function foo (FooOptions $opts) {
  ...
}

Of course, you might pay for that with extra verbosity setting up the FooOptions object. There's no totally-free ride, unfortunately.




回答8:


Normally you can't but I think there a lot of ways to pass named arguments to a PHP function. Personally I relay on the definition using arrays and just call what I need to pass:

class Test{
    public $a  = false;
    private $b = false;
    public $c  = false;
    public $d  = false;
    public $e  = false;
    public function _factory(){
        $args    = func_get_args();
        $args    = $args[0];
        $this->a = array_key_exists("a",$args) ? $args["a"] : 0;
        $this->b = array_key_exists("b",$args) ? $args["b"] : 0;
        $this->c = array_key_exists("c",$args) ? $args["c"] : 0;
        $this->d = array_key_exists("d",$args) ? $args["d"] : 0;
        $this->e = array_key_exists("e",$args) ? $args["e"] : 0;
    }
    public function show(){
        var_dump($this);
    }
}


$test = new Test();
$args["c"]=999;
$test->_factory($args);
$test->show();

live example here: http://sandbox.onlinephpfunctions.com/code/d7f27c6e504737482d396cbd6cdf1cc118e8c1ff

If I have to pass 10 arguments, and 3 of them are the data I really need, is NOT EVEN SMART to pass into the function something like

return myfunction(false,false,10,false,false,"date",false,false,false,"desc");

With the approach I'm giving, you can setup any of the 10 arguments into an array:

$arr['count']=10;
$arr['type']="date";
$arr['order']="desc";
return myfunction($arr);

I have a post in my blog explaining this process in more details.

http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php




回答9:


Here's what I've been using. A function definition takes one optional array argument which specifies the optional named arguments:

function func($arg, $options = Array()) {
  $defaults = Array('foo' => 1.0,
                    'bar' => FALSE);
  $options = array_merge($default, $options);

  // Normal function body here.  Use $options['foo'] and
  // $options['bar'] to fetch named parameter values.
  ...
}

You can normally call without any named arguments:

func("xyzzy")

To specify an optional named argument, pass it in the optional array:

func("xyzzy", Array('foo' => 5.7))



回答10:


No not really. There are a few alternatives to it you could use.

test(null,null,"hello")

Or pass an array:

test(array('c' => "hello"));

Then, the function could be:

function test($array) { 
    $c = isset($array[c]) ? $array[c] : '';
}

Or add a function in between, but i would not suggest this:

function ctest($c) { test('','',$c); }



回答11:


Try function test ($a="",$b="",&$c=""){}

Putting & before the $c




回答12:


I dont think so... If you need to call, for example, the substr function, that has 3 params, and want to set the $length without set the $start, you'll be forced to do so.

substr($str,0,10);

a nice way to override this is to always use arrays for parameters




回答13:


Simple answer. No you can't.
You could try getting around it by passing in an object/array or using some other Dependency injection patterns.

Also, try to use nulls rather than empty strings as it's more definite to test for their existence using is_null()

eg:

function test ($a=null,$b=null,$c=null){
 if (is_null($a) {
  //do something about $a
 }
 if (is_null($b) {
  //do something about $b
 }
 if (is_null($c) {
  //do something about $c
 }
}

to call this:

test(null,null,"Hello");



回答14:


In very short, sometimes yes, by using reflection and typed variables. However I think this is probably not what you are after.

A better solution to your problem is probably to pass in the 3 arguments as functions handle the missing one inside your function yourself

<?php  
   function test(array $params)
   {
     //Check for nulls etc etc
     $a = $params['a'];
     $b = $params['b'];
     ...etc etc
   }



回答15:


You can't do it the python way. Anway, you could pass an associative array and than use the array entries by their name:

function test ($args=array('a'=>'','b'=>'','c'=>''))
{
    // do something
}

test(array('c'=>'Hello'));

This doesn't reduce the typing, but at least it's more descriptive, having the arguments' names visible and readable in the call.




回答16:


Here is a work around:

function set_param_defaults($params) {
  foreach($params['default_values'] as $arg_name => $arg_value) {
    if (!isset($params[$arg_name])) {
      $params[$arg_name] = $arg_value;
    }
  }

  return $params;
}

function foo($z, $x = null, $y = null) {
  $default_values = ['x' => 'default value for x', 'y' => 'default value for y'];
  $params = set_param_defaults(get_defined_vars());

  print "$z\n";
  print $params['x'] . "\n";
  print $params['y'] . "\n";
}

foo('set z value', null, 'set y value');
print "\n";
foo('set z value', 'set x value');

ALTERNATIVELY: Personally I would go with this method.

function foo($z, $x_y) {
  $x_y += ['x' => 'default value for x', 'y' => 'default value for y'];

  print "$z\n";
  print $x_y['x'] . "\n";
  print $x_y['y'] . "\n";
}

foo('set z value', ['y' => 'set y value']);
print "\n";
foo('set z value', ['x' => 'set x value']);

Print outs for both examples.

1st call:

  • set z value
  • default value for x
  • set y value

2nd call:

  • set z value
  • set x value
  • default value for y



回答17:


Just use the associative array pattern Drupal uses. For optional defaulted arguments, just accept an $options argument which is an associative array. Then use the array + operator to set any missing keys in the array.

function foo ($a_required_parameter, $options = array()) {
    $options += array(
        'b' => '',
        'c' => '',
    );
    // whatever
}

foo('a', array('c' => 'c’s value')); // No need to pass b when specifying c.


来源:https://stackoverflow.com/questions/1342908/named-php-optional-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!