0

I'm aware that you can have PHP functions with optional arguments like so:

function do_something($argument = null) 
{
   // argument not provided
   if ($argument === null) 
      ........
}

Consider the case that null/false and other values are all valid arguments to my function. How can I determine whether an argument was provided or not?

do_something(null);            // argument provided
do_something(false);           // argument provided
do_something(0);               // argument provided
do_something("test");          // argument provided
do_something(new stdClass());  // argument provided
do_something();                // nothing provided

How can I detect the last case? I have thought about using func_num_args which would work in most cases but it doesn't work if I have several optional arguments.

Is there anything that solves this problem?

0

4 Answers 4

2

func_num_args() should work exactly as you want it to, because you might be assuming something that's actually not the case: You can't have optional arguments left out if they are in the middle of your arguments list.

So let's look at this function:

function test1 ($param1 = null, $param2 = null) {
   return func_num_args();
}

If I call that with different parameter combinations I get the following results:

test1()              => 0
test1(true)          => 1
test1(true, true)    => 2

There is just no way to call the function in a way where $param2 would be set while $param1 isn't. So you can map every possible output of func_num_args() to exactly one parameter configuration.

In the example above you can rely on the fact that

  • if the return value is 1, $param2 definitely hasn't been set, while $param1 has been.
  • For 0 it's 100% sure that neither one has been given.
  • And, of course, if it's 2 both are there.

What you actually would need are named parameters, as many other languages have them. PHP doesn't at the moment. NikiC actually wrote an RFC that suggests the addition of named parameters to PHP, but I think that's still way off in the future. You can check that out here: https://wiki.php.net/rfc/named_params

As these are not yet available, here are a few workarounds you can try:

Workaround 1

If you really need to be able to have all the parameters optional, try a parameter array:

function test1 (array $opts) {
    if (!isset($opts['opt1'])) { $opts['opt1'] = 'default1'; }
    if (!isset($opts['opt2'])) { $opts['opt2'] = 'default2'; }
}

Then you can call it like this:

test1(array('opt2' => true))

It would set the first parameter to "default1" while keeping the second. And there are definitely better and more elegant ways to do this (e.g. using an object instead), but the general idea is the same.

Workaround 2

You could also go with alias functions:

function test ($param1, $patam2) { ... ]
function testNoParam1 ($param2) {
    test("default1", $param2);
}

That at least makes it very easy to read, but of course you need to pick the right function depending on the parameters you have.

Workaround 3

By adding a lot of additional code you could get really fancy and use a FactoryObject:

class FunctionExecutor {
    private $param1 = "default1";
    private $param2 = "default2";

    public function param1($val) {
       $this->param1 = $val;
       return $this;
    }

    public function param2($val) {
       $this->param2 = $val;
       return $this;
    }

    public function execute() {
       return yourFunction($this->param1, $this->param2);
    }
}

This could be used like this:

$doSomething = new FunctionExecutor();
$returnValue = $doSomething->param2(42)->execute();

In this approach it would probably be a better idea to actually put your function into the object instead of defining it globally. Anyway...this is definitely a possibility, but not the most practical one. Just wanted to add it, because it has some benefits.

Sign up to request clarification or add additional context in comments.

5 Comments

How can I provide an argument for the second parameter only? test1(OPTIONAL, null)
You can't. If you need something like this, use an array as the only parameter of the function and check if the values you need have been set in there. Ideally you would use an associative array for this.
My current solution is to have a constant defined with a random string and test equality with that test1(DEFAULT_VALUE_STRING, null) but it's not good code. The array option is certainly nicer but does require extra code inside and outside the function. Is there any news about named arguments coming to PHP in the future?
If you want to avoid additional "logic" to make this work, you could also just define aliases for your function with different parameter lists and then call the original functions with default values for all the missing parameters. Still additional code, but at least no logic.
I added another possibility that just popped into my head. Probably not what you're looking for, because it adds quite some code, but hey...it's fun and looks cool. ;)
0

perhaps this will help: http://www.php.net//manual/en/function.func-get-args.php

$args = func_get_args();
if(!isset($arg[0])) {
    echo 'no argument';
}

or

isset(func_get_arg(0));

Comments

0

Passing "null", "0", or "false" means that you allocate memory to store a variable, regardless it's scope, type, or size. Then it is used as a parameter to a function.

In PHP you cannot override functions by arguments, but you can access them by calling the "func_get_args()", and this is the only way to handle different numbers / types of arguments passed to a function:

function do_something() {
 $args = func_get_args();

 //do_something(stdClass, 1)
 if($args[0] instanceof stdClass && is_numeric($args[1])) {
     //handle
     //return 

 //do_something(1, "string")
 } else if(is_numeric($args[0]) && is_string($args[1])) {
     //handle
     //return
 }
 throw new Exception('invalid arguments');
}

do_something(new StdClass(), 100); //ok
do_something(100, "hell world") // ok
do_someting(); //throws Exception('invalid arguments');

Comments

0

In PHP 7, you can do:

function action(...$args) {
    if (count($args) === 0) {
        return action_default();
    }
    $var1 = array_shift($args);
    $var2 = array_shift($args);
    $var3 = array_shift($args);
    // etc.
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.