133

I've written a PHP function that can accept 10 parameters, but only 2 are required. Sometimes, I want to define the eighth parameter, but I don't want to type in empty strings for each of the parameters until I reach the eighth.

One idea I had was to pass an abstracted function with an array of parameters which passes it along to the real function.

Is there a better way to set up the function so I can pass in only the parameters I want?

Jakub Muda
  • 6,008
  • 10
  • 37
  • 56
user481826
  • 1,365
  • 2
  • 9
  • 4
  • 4
    Related: http://stackoverflow.com/questions/2112913 – Pekka Oct 20 '10 at 14:32
  • That's strange. Built-in functions in php may have optional parameters. So why can't we build functions like that? – Rodrigo Mar 04 '16 at 13:00
  • 6
    Note that **many of these answers are OUTDATED**... PHP now supports [functions with **variable-length argument lists**](https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list). – ashleedawg May 04 '19 at 00:29

16 Answers16

72

What I have done in this case is pass an array, where the key is the parameter name, and the value is the value.

$optional = array(
  "param" => $param1,
  "param2" => $param2
);

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
  • 4,282
  • 1
  • 30
  • 53
  • For your example, wouldn't $optional need to be set global within the function? – user481826 Oct 20 '10 at 23:59
  • 1
    global? no..? You create that array before you call the function, and you pass it. My code is an example of Matt Balls description of what should be done. – Rabbott Oct 21 '10 at 18:13
  • There is more that can be done that just the "use an array" suggestions - take a look at Walf's answer to [a similar question](http://stackoverflow.com/questions/690599/any-way-to-specify-optional-parameter-values-in-php/32098964#32098964) and the more in-depth example in the same thread – DJDave Mar 16 '16 at 13:10
68

Make the function take one parameter: an array. Pass in the actual parameters as values in the array.


Edit: the link in Pekka's comment just about sums it up.

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 2
    That's strange. Built-in functions in php may have optional parameters. So why can't we build functions like that? – Rodrigo Mar 04 '16 at 12:59
  • 2
    @Rodrigo it's absolutely doable to define functions like those. They're positional optional though, which is pretty lousy for anything beyond a single optional parameter. – Matt Ball Mar 04 '16 at 17:39
  • 1
    Ok, I was trying with [ ], now I see how to do it here: http://stackoverflow.com/a/34869/1086511 – Rodrigo Mar 04 '16 at 17:46
  • There is more that can be done that just the "use an array" suggestion - take a look at Walf's answer to [a similar question](http://stackoverflow.com/questions/690599/any-way-to-specify-optional-parameter-values-in-php/32098964#32098964) and the more in-depth example in the same thread – DJDave Mar 16 '16 at 13:07
57

To accomplish what you want, use an array Like Rabbot said (though this can become a pain to document/maintain if used excessively). Or just use the traditional optional args.

//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
  //Do stuff
}
my_func('Hi', 'World', null, null, 'Red');

However, I usually find that when I start writing a function/method with that many arguments - more often than not it is a code smell, and can be re-factored/abstracted into something much cleaner.

//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
  return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');
Community
  • 1
  • 1
Kayla Rose
  • 1,293
  • 10
  • 12
  • On 2010, notions such as 'code smell', 'refactoring' or 'code maintenance' were not popular in our community. You had a step before most of us :) – Billal Begueradj Mar 13 '20 at 13:37
23

You can just set the default value to null.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Blake Stevenson
  • 231
  • 2
  • 3
17

In PHP 5.6 and later, argument lists may include the ... token to denote that the function accepts a variable number of arguments. The arguments will be passed into the given variable as an array; for example:

Example Using ... to access variable arguments

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

The above example will output:

10

Variable-length argument lists PHP Documentation

Mentos1386
  • 308
  • 4
  • 9
  • This response deserves more points. Not suitable for my specific case scenario but good information and simple to understand. PHP 7.3 is coming shortly! 5.6 and 7 are EOL. – AdheneManx Dec 08 '18 at 02:23
15

Starting with PHP 8 you are able to use named arguments:

function namedParameters($paramOne, $paramTwo, $paramThree = 'test', $paramFour = null)
{
    dd($paramOne, $paramTwo, $paramThree, $paramFour);
}

We can now call this function with the required params and only the optinal params, that we want to differ from the default value which we specified in the function.

namedParameters('one', 'two', paramFour: 'four');

Result:

// "one", "two", "test", "four"
Matthias
  • 3,729
  • 22
  • 37
  • 1
    This is the best solution especially when you are dealing with existing code/functions. Hard to change parameters into an array for functions used all over the codebase. – Chiwda Aug 07 '23 at 14:42
13

NOTE: This is an old answer, for PHP 5.5 and below. PHP 5.6+ supports default arguments

In PHP 5.5 and below, you can achieve this by using one of these 2 methods:

  • using the func_num_args() and func_get_arg() functions;
  • using NULL arguments;

How to use

function method_1()
{
  $arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
  $arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}

function method_2($arg1 = null, $arg2 = null)
{
  $arg1 = $arg1? $arg1: "default_value_for_arg1";
  $arg2 = $arg2? $arg2: "default_value_for_arg2";
}

I prefer the second method because it's clean and easy to understand, but sometimes you may need the first method.

Community
  • 1
  • 1
Daniel Loureiro
  • 4,595
  • 34
  • 48
  • 1
    You need the double "=" here or all the expressions will return true. Also, the expressions in the 2nd example will always return true because a variable is always equal to itself. – chuckieDub May 14 '13 at 13:51
  • good point, but this actually works. In PHP this code `$x = null; if ($x) echo "true"; else echo "false";` will print "false", even if the $x var having a value ("null" in this code). Also, in both methods we are using the ternary operator, so it's correct use just one "=". If you test with `method(); method(1); method(1, 2);`, then the first call will associate arg1 and arg2 with the defaults values, the second call will associate the second arg with the default value and "1" for the first arg. The last call will not associate default values. – Daniel Loureiro Jun 09 '13 at 00:06
  • 1
    function method_2($arg1 = "default_value_fot_arg1", $arg2 = "default_value_fot_arg2") { so php deal with parameter stuff and also you may pass null as parameter (why people use null I dont know) – nerkn Mar 31 '17 at 07:39
  • 1
    @nerkn, you're right, PHP currently supports default arguments. Lol, I remember when we needed to make a lot of workarounds to achieve simple things. Good times :P You can still see those approaches in old codes (pre-5.5), although. – Daniel Loureiro Mar 31 '17 at 09:00
4

I think, you can use objects as params-transportes, too.

$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);

function theFunction($fparam){      
  return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}

Of course, you have to set default values for "optParam8" and "optParam2" in this function, in other case you will get "Notice: Undefined property: stdClass::$optParam2"

If using arrays as function parameters, I like this way to set default values:

function theFunction($fparam){
   $default = array(
      'opt1' => 'nothing',
      'opt2' => 1
   );
   if(is_array($fparam)){
      $fparam = array_merge($default, $fparam);
   }else{
      $fparam = $default;
   }
   //now, the default values are overwritten by these passed by $fparam
   return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}
psad
  • 104
  • 1
  • 7
2

I know this is an old post, but i was having a problem like the OP and this is what i came up with.

Example of array you could pass. You could re order this if a particular order was required, but for this question this will do what is asked.

$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');

This is manageable, easy to read and the data extraction points can be added and removed at a moments notice anywhere in coding and still avoid a massive rewrite. I used integer keys to tally with the OP original question but string keys could be used just as easily. In fact for readability I would advise it.

Stick this in an external file for ease

function unknown_number_arguments($argument_set) {

    foreach ($argument_set as $key => $value) {

        # create a switch with all the cases you need. as you loop the array 
        # keys only your submitted $keys values will be found with the switch. 
        switch ($key) {
            case 1:
                # do stuff with $value
                break;
            case 2:
                # do stuff with $value;
                break;
            case 3:
                # key 3 omitted, this wont execute 
                break;
            case 5:
                # do stuff with $value;
                break;
            case 8:
                # do stuff with $value;
                break;
            default:
                # no match from the array, do error logging?
                break;
        }
    }
return;
}

put this at the start if the file.

$argument_set = array(); 

Just use these to assign the next piece of data use numbering/naming according to where the data is coming from.

$argument_set[1][] = $some_variable; 

And finally pass the array

unknown_number_arguments($argument_set);
CodingInTheUK
  • 930
  • 7
  • 16
2

If only two values are required to create the object with a valid state, you could simply remove all the other optional arguments and provide setters for them (unless you dont want them to changed at runtime). Then just instantiate the object with the two required arguments and set the others as needed through the setter.

Further reading

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
2
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

You can make a regular function and then add your optional variables by giving them a default Null value.

A Null is still a value, if you don't call the function with a value for that variable, it won't be empty so no error.

  • 2
    Can you explain all that further? The given code is syntactically invalid, as variable names cannot start with a number – Nico Haase Jun 14 '19 at 12:40
2

As of PHP 7.1.0, type declarations can be marked nullable by prefixing the type name with a question mark (?). This signifies that the value can be of the specified type or null

<?php
    function name(?string $varname){
        echo is_null($varname);
    }
    name();
    name('hey');
?>

for more info: Click here

0

If you are commonly just passing in the 8th value, you can reorder your parameters so it is first. You only need to specify parameters up until the last one you want to set.

If you are using different values, you have 2 options.

One would be to create a set of wrapper functions that take different parameters and set the defaults on the others. This is useful if you only use a few combinations, but can get very messy quickly.

The other option is to pass an array where the keys are the names of the parameters. You can then just check if there is a value in the array with a key, and if not use the default. But again, this can get messy and add a lot of extra code if you have a lot of parameters.

Alan Geleynse
  • 24,821
  • 5
  • 46
  • 55
0

PHP allows default arguments (link). In your case, you could define all the parameters from 3 to 8 as NULL or as an empty string "" depending on your function code. In this way, you can call the function only using the first two parameters.

For example:

<?php
  function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}
mastropi
  • 1,354
  • 1
  • 10
  • 14
  • Interesting idea... however your proposal does not solve the problem. In fact, if you add information on what argument is being echoed (e.g. by using `echo " this is arg3: " . $arg3;`, etc., you will see that calling e.g. `yourFunction(3, 2, $arg8=5);` will print `32 this is arg3: 5`. The problem is that the parameter position still matters when passing optional parameters in PHP... parameter names _are not enough_ to map parameter values to parameter names. – mastropi Mar 31 '20 at 22:21
0

Just set Null to ignore parameters that you don't want to use and then set the parameter needed according to the position.

 function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
    for ($i=1; $i<9; $i++){
        $varName = "p$i";
        if (isset($$varName)){
            echo $varName." = ".$$varName."<br>\n";
        }
    }
}   

myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );
-4
func( "1", "2", default, default, default, default, default, "eight" );
Flinsch
  • 4,296
  • 1
  • 20
  • 29
  • 1
    This is not valid PHP. `default` is a [keyword in PHP](http://php.net/manual/en/reserved.keywords.php). – Pang Oct 07 '16 at 01:01