4

I don't know how or where I got this idea in my head but for some reason I thought this was possible. Obviously after testing it doesn't work, but is there a way to make it work? I want to set $value2 without having to enter anything at all for $value1.

function test($value1 = 1, $value2 = 2) {

echo 'Value 1: '.$value1.'<br />';
echo 'Value 2: '.$value2.'<br />';

}

test($value2 = 3);

// output
Value 1: 3
Value 2: 2
Clint C.
  • 678
  • 13
  • 31
  • Unpossible. You really want this behavior, switch args 1 and 2 in the signature. – Mike Purcell Apr 16 '12 at 20:20
  • Yep, you're looking for keyword arguments which are not available in PHP but e.g. in Python. – Raphael Michel Apr 16 '12 at 20:23
  • possible duplicate of [PHP Using Default Arguments in a Function](http://stackoverflow.com/questions/9166914/php-using-default-arguments-in-a-function) – John Flatness Apr 16 '12 at 20:23
  • Thanks for all of the answers so far. Yes, the main point was hoping I didn't have to do a work around, but obviously it's not possible. I wonder why this wasn't made possible in php? – Clint C. Apr 16 '12 at 20:32

8 Answers8

8

Its not entirely possible the way you want.

Simply,

function test($value1 = null, $value2 = 2) {

echo 'Value 1: '.$value1.'<br />';
echo 'Value 2: '.$value2.'<br />';

}

test(NULL, $value2 = 3);

Or, Use array as parameters

function test($array) {

if(isset($array['value1'])) echo 'Value 1: '.$array['value1'].'<br />';
if(isset($array['value2'])) echo 'Value 2: '.$array['value2'].'<br />';

}

test(array('value2' => 3));

Update:

My another attempt

function test() {
  $args = func_get_args();
  $count = count($args);
  if($count==1) { test1Arg($args[0]); }
  elseif($count == 2) { test2Arg($args[0],$args[1]); }
  else { //void; }
}

function test1Arg($arg1) {
   //Do something for only one argument
}
function test2Arg($arg1,$arg2) {
   //Do something for two args
}
Starx
  • 77,474
  • 47
  • 185
  • 261
  • 1
    OP is aware of this solution: "I want to set $value2 without having to enter anything at all for $value1". – Mike Purcell Apr 16 '12 at 20:20
  • +1 for the effort, but the array as a param solution is getting away form the essence of the problem, in my opinion – Kristian Apr 16 '12 at 20:22
  • 2
    `test(NULL, $value2 = 3);` is leading to unwanted behaviour as the `$value2 = ` does something completely different from what the OP is wanting to do and is misleading when being read. – Raphael Michel Apr 16 '12 at 20:22
  • The idea with arrays you edited into this answer is good, sadly I'm unable to change my vote. – Raphael Michel Apr 16 '12 at 20:28
  • @rami, I edited, SO you can change your vote, and I updated with another way too. – Starx Apr 16 '12 at 20:33
  • Thanks for all the options Starx. I thought of some of the solutions as well. I was just hoping I wouldn't have to change things up! Appreciate it. – Clint C. Apr 16 '12 at 20:41
  • Passing the array as an arg is the best solution imo. Removing DV. – Mike Purcell Apr 16 '12 at 20:55
4

What you're trying to do is called "keyword arguments" or "named arguments" and is not available in PHP in contrast to other scripting languages like Python.

If you have functions with hundreds of parameters and really want to achieve a more flexible solution than what PHP comes with, you could build your own workaround with arrays or objects, maybe in conjunction with func_get_args(). But this obviously isn't as beautiful as real keyword arguments.

EoghanM
  • 25,161
  • 23
  • 90
  • 123
Raphael Michel
  • 854
  • 1
  • 9
  • 18
1

For a simple function, it's likely impractical to jump into OOP; however, to throw more fuel to this variation fire, this is a case where you could probably use OOP, for better or worse.

Default function parameters are unwieldy to swap around for your convenience, however, that's not the case with extended classes. Those are meant to be varied and mutated as the need arises.

class test {
    var $value1 = 1;
    var $value2 = 2;

    function __construct() {
        printf( "Value 1 = %s, value 2 = %s\n", $this->value1, $this->value2 );
    }
}

class test2 extends test {
    var $value2 = 42;
}

$me = new test();   // outputs Value 1 = 1, value 2 = 2
$me2 = new test2(); // outputs Value 1 = 1, value 2 = 42

Once again, not the practical solution for simplest of tasks, but, it will allow you to mutate code fragments at will. Rethink whether you can rewrite your code to take advantage of this style.

pp19dd
  • 3,625
  • 2
  • 16
  • 21
0
function test($value1 = null, $value2 = null) {
  $value1 = $value1 ?: 1;
  $value2 = $value2 ?: 2;
  echo 'Value 1: '.$value1.'<br />';
  echo 'Value 2: '.$value2.'<br />';
}

test(null, 3);
KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • 1
    As far as I can see, OP is aware of this solution so I don't think it is what he wants. – Raphael Michel Apr 16 '12 at 20:23
  • Thanks for your hint, but thats the way it works, even if the OP doesn't like it. – KingCrunch Apr 16 '12 at 20:27
  • But it's not what you want if you have a function with fifteen arguments. See my, Starx's or TRiG's answer – I guess in this case an array is the best solution – Raphael Michel Apr 16 '12 at 20:30
  • You really have functions/methods with fifteen arguments?!? Oo Sounds like a design flaw :X – KingCrunch Apr 16 '12 at 21:11
  • I don't. But simetimes it does make sense. – Raphael Michel Apr 16 '12 at 21:16
  • No, it doesn't ^^ At the end at least value objects can help reducing the number of arguments. There are pattern (`Builder` for example), which help creating value objects, or even avoid the requirement for such blown methods completely. "Too much arguments" is a code smell, that is avoidable. – KingCrunch Apr 16 '12 at 21:20
  • Value objects are somehow what I proposed in my answer („build your own workaround with arrays or objects“). Wordpress uses arrays, objects might be even better. So in that way I agree with you. – Raphael Michel Apr 16 '12 at 21:23
0

AFAIK, you can't modify the values of the arguments the way you want it. The manual even says this is invalid (http://php.net/manual/en/functions.arguments.php#example-153).

What you're doing withtest($value2 = 3); is first assigning to a new variable $value2 a value of 3 and then sending it as the first parameter of test.

However, you can create a function where when you send a null parameter, it gets a value assigned:

function test($value1 = NULL, $value2 = 2) {

    if ($value1 === NULL)
        $value1 = 1 // $value1 default value

    echo 'Value 1: '.$value1.'<br />';
    echo 'Value 2: '.$value2.'<br />';

}

test(NULL, 3);

// output
Value 1: 1
Value 2: 3

Or well, change the default values of the variables:

function test($value2 = 2, $value1 = 1) {

    echo 'Value 1: '.$value1.'<br />';
    echo 'Value 2: '.$value2.'<br />';

}

test(3);

// output
Value 1: 1
Value 2: 3
Adonais
  • 1,294
  • 6
  • 12
0

This is not possible in PHP, as handy as it would be, but there are a couple of ways around it.

function func($val1=null, $val2=null) {
    // Set default values.
    if (!$val1) $val1 = 1;
    if (!$val2) $val2 = 2;
    // Your code here.
}

func(null, 74); // Uses the default value of 1 for $val1.

Or use an array (much handier if you have a very long list of arguments):

function func($arr) {
    // Set default values.
    $val1 = isset($arr[1]) ? $arr[1] : 1;
    $val2 = isset($arr[2]) ? $arr[2] : 2;
    // Your code here.
}

func(array(2 => 74)); // Uses the default value of 1 for $val1.

Actually, I have a function which takes the array, the key, and the default, and returns a value, so I could write those lines as

$val1 = Core::val($arr, 1, 1); // array, key, default
$val2 = Core::val($arr, 2, 2);
TRiG
  • 10,148
  • 7
  • 57
  • 107
-1

It is considered bad practice to have arguments with default values come after args that do not. the reason being that its not allowed to simply write a function with a bunch of commas in it.

In your case, you should pass a value to both parameters. Even if the value is null.

Kristian
  • 21,204
  • 19
  • 101
  • 176
-1

Maybe this is what u r looking for:

    function test($value1, $value2) 
    {

      if ($value1!="") 
      {
         echo 'Value 1: '.$value1.'<br />'; 
      }
      else
      {
         echo 'Value 1: 3'<br />'; 
      }
      echo 'Value 2: '.$value2.'<br />';

    }

    test("", $value2 = 3);

    // output
    Value 1: 3
    Value 2: 2
dimmat
  • 195
  • 1
  • 3
  • 10
  • As far as I can see, OP is aware of this solution so I don't think it is what he wants (he wants to pass no value vor $value1 AT ALL, which absolutely makes sense if you have a bunch of arguments.) – Raphael Michel Apr 16 '12 at 20:24
  • Rami, thanks for commenting but there is no simpler way. Unfortunately, argument for value1 MUST be given. – dimmat Apr 16 '12 at 20:34