Let\'s say I\'ve got a PHP function foo:
function foo($firstName = \'john\', $lastName = \'doe\') {
echo $firstName . \" \" . $lastName;
}
// foo(); --&g
If this is used very often, just define a new specialized function :
function person($firstName = 'john', $lastName = 'doe') {
return $firstName . " " . $lastName;
}
function usualFirtNamedPerson($lastName = 'doe') {
return person('john', $lastName);
}
print(usualFirtNamedPerson('smith')); --> john smith
Note that you could also change the default value of $lastname in the process if you wish.
When a new function is estimated overbloated, just call you function with all parameters. If you want to make it more clear, you can prestore your literals in fin named variable or use comments.
$firstName = 'Zeno';
$lastName = 'of Elea';
print(person($firstName, $lastName));
print(person(/* $firstName = */ 'Bertrand', /* $lastName = */ 'Russel'));
Ok, this is not as short and elegant as person($lastName='Lennon')
, but it seems you can't have it in PHP. And that's not the sexiest way to code it, with super metaprogramming trick or whatever, but what solution would you prefer to encounter in a maintenance process?
Arguments need to be passed in order by position, you cannot skip a parameter per se; you'll have to supply the default parameter value in order to skip it. Arguably that defeats the purpose of what you're trying to achieve.
Without rewriting your function to accept parameters differently, here's a call-time way to work around this:
$func = 'foo';
$args = ['lastName' => 'Smith'];
$ref = new ReflectionFunction($func);
$ref->invokeArgs(array_map(function (ReflectionParameter $param) use ($args) {
if (array_key_exists($param->getName(), $args)) {
return $args[$param->getName()];
}
if ($param->isOptional()) {
return $param->getDefaultValue();
}
throw new InvalidArgumentException("{$param->getName()} is not optional");
}, $ref->getParameters()));
In other words, you're using reflection to inspect the function's parameters and map them to the available parameters by name, skipping optional parameters with their default value. Yes, this is ugly and cumbersome. You could use this sample to create a function like:
call_func_with_args_by_name('foo', ['lastName' => 'Smith']);
If you have multiple optional parameters, one solution is to pass a single parameter that is a hash-array:
function foo(array $params = array()) {
$firstName = array_key_exists("firstName", $params) ?
$params["firstName"] : "";
$lastName = array_key_exists("lastName", $params) ?
$params["lastName"] : "";
echo $firstName . " " . $lastName;
}
foo(['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.
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'));
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
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.