假设我有一个 PHP 函数 foo:
function foo($firstName = 'john', $lastName = 'doe') {
echo $firstName . " " . $lastName;
}
// foo(); --> john doe
有没有办法指定只有第二个可选参数?例如:
foo($lastName='smith'); // output: john smith
假设我有一个 PHP 函数 foo:
function foo($firstName = 'john', $lastName = 'doe') {
echo $firstName . " " . $lastName;
}
// foo(); --> john doe
有没有办法指定只有第二个可选参数?foo($lastName='smith'); // output: john smith
PHP本身不支持函数的命名参数。然而,有一些方法可以解决这个问题:
一种变化的数组技巧,允许更轻松地设置默认值:
function foo($arguments) {
$defaults = array(
'firstName' => 'john',
'lastName' => 'doe',
);
$arguments = array_merge($defaults, $arguments);
echo $arguments['firstName'] . ' ' . $arguments['lastName'];
}
使用方法:
foo(array('lastName' => 'smith')); // output: john smith
$arguments += $defaults;
更加简洁。 - Walf您可以对您的代码进行简单的重构:
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
如果您有多个可选参数,一种解决方案是传递一个单一的参数,它是一个哈希数组:
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']);
不行。通常的做法是使用一些启发式算法来确定隐含的参数,例如字符串长度、输入类型等。
一般来说,你应该按照最需要到最不需要的顺序编写函数参数。
您想要的方式:不行。
您可以使用一些特殊标记,如NULL来表示值未提供:
function foo($firstName, $lastName = 'doe') {
if (is_null($firstName))
$firstName = 'john';
echo $firstName . " " . $lastName;
}
foo(null, 'smith');
PHP 8引入了命名参数,因此现在可以指定传递给函数的参数。
在 PHP 8 之前:
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
在 PHP 8 之后:
htmlspecialchars($string, double_encode: false);
extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));
function test_params($a, $b, $arrOptionalParams = array()) {
$arrDefaults = array('c' => 'sat',
'd' => 'mat');
extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));
echo "$a $b $c on the $d";
}
然后像这样调用它
test_params('The', 'dog', array('c' => 'stood', 'd' => 'donkey'));
test_params('The', 'cat', array('d' => 'donkey'));
test_params('A', 'dog', array('c' => 'stood'));
结果:
狗站在驴子上。
猫坐在驴子上。
一只狗站在地席上。
参数需要按位置顺序传递,不能跳过某个参数;您必须提供默认参数值才能跳过它。可以说这违背了您尝试实现的目的。
如果不重新编写函数以不同方式接受参数,则可以通过调用时间来解决此问题:
$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()));
call_func_with_args_by_name('foo', ['lastName' => 'Smith']);
function some_func($required_parameter, &$optional_reference_parameter = null, $options = null) {
$options_default = array(
'foo' => null,
);
extract($options ? array_intersect_key($options, $options_default) + $options_default : $options_default);
unset($options, $options_default);
//do stuff like
if ($foo !== null) {
bar();
}
}
$foo
),并防止创建任何没有默认值的变量。这是为了防止任何人意外地覆盖函数内的其他参数或其他变量。