在PHP 4/5中是否可以在调用时指定一个命名的可选参数,跳过你不想指定的参数(比如在python中)?
类似的东西:
function foo($a,$b='', $c='') {
// whatever
}
foo("hello", $c="bar"); // we want $b as the default, but specify $c
由于
答案 0 :(得分:21)
不,这是不可能的:如果要传递第三个参数,则必须传递第二个参数。并且命名参数也是不可能的。
一个“解决方案”是只使用一个参数,一个数组,并始终传递它......但不要总是在其中定义所有内容。
例如:
function foo($params) {
var_dump($params);
}
以这种方式调用它:
foo(array(
'a' => 'hello',
));
foo(array(
'a' => 'hello',
'c' => 'glop',
));
foo(array(
'a' => 'hello',
'test' => 'another one',
));
会得到这个输出:
array
'a' => string 'hello' (length=5)
array
'a' => string 'hello' (length=5)
'c' => string 'glop' (length=4)
array
'a' => string 'hello' (length=5)
'test' => string 'another one' (length=11)
但我真的不喜欢这个解决方案:
所以我只在非常具体的情况下使用它 - 对于有很多可选参数的函数,例如......
答案 1 :(得分:6)
不,PHP无法按名称传递参数。
如果你的函数需要很多参数并且所有参数都有默认值,你可以考虑让函数接受一个参数数组:
function test (array $args) {
$defaults = array('a' => '', 'b' => '', 'c' => '');
$args = array_merge($defaults, array_intersect_key($args, $defaults));
list($a, $b, $c) = array_values($args);
// an alternative to list(): extract($args);
// you can now use $a, $b, $c
}
答案 2 :(得分:3)
不,不是。
你可以做到这一点的唯一方法是使用带有命名键的数组,而不是。
答案 3 :(得分:3)
从 PHP 5.4 开始,你有简写数组语法(不是nessecary指定数组繁琐"数组"而是使用" []")。
您可以通过多种方式模仿命名参数,这可能是一种简单明了的方法:
bar('one', ['a1' => 'two', 'bar' => 'three', 'foo' => 'four']);
// output: twothreefour
function bar ($a1, $kwargs = ['bar' => null, 'foo' => null]) {
extract($kwargs);
echo $a1;
echo $bar;
echo $foo;
}
答案 4 :(得分:2)
使用PHP,参数的顺序才是最重要的。您不能指定一个特定的参数,而是可以通过传递NULL来跳过参数,只要您不介意函数中具有NULL值的值。
foo("hello", NULL, "bar");
答案 5 :(得分:2)
PHP 8 will be released on November 26, 2020.(PHP感恩节快乐!)
在此主要版本中,“ 命名参数”(又称“ 命名参数”)为开发人员在调用本机和自定义函数时提供了一些非常酷的新技术。
现在可以使用第一个参数(因为没有默认值)来调用此问题中的自定义函数,然后仅使用第三个参数(例如,{Demo)
function foo($a, $b = '', $c = '') {
echo $a . '&' . $b . '&' . $c;
}
foo("hello", c: "bar");
// output: hello&&bar
请注意,第二个参数不需要在函数调用中声明,因为它已定义了默认值-默认值将在函数内自动使用。
此新功能的部分优点在于,您无需注意命名参数的顺序-它们的声明顺序无关紧要。 foo(c: "bar", a: "hello");的工作原理相同。具有“跳过”声明和编写声明性参数的能力将提高脚本的可读性。这项新功能的唯一缺点是函数调用会有点膨胀,但是我(和许多其他人)认为收益超过了这种“成本”。
这里是一个本机函数的示例,它省略了limit
参数,以正常顺序写入参数,并声明了一个引用变量。 (Demo)
echo preg_replace(
subject: 'Hello 7',
pattern: '/[a-z ]/',
count: $counted,
replacement: ''
)
. " & " . $counted;
// output: H7 & 5
关于此新功能还有更多要说的。您甚至可以使用关联数组将命名参数传递给该函数,在该函数中,可以使用spread / splat运算符来解压缩数据!
(*请注意声明参考变量时稍有不同。)(Demo)
$params = [
'subject' => 'Hello 7', // normally third parameter
'pattern' => '/[a-z ]/', // normally first parameter
// 'limit' // normally fourth parameter, omitted for this demonstration; the default -1 will be used
'count' => &$counted, // normally fifth parameter
// ^-- don't forget to make it modifiable!
'replacement' => '', // normally second parameter
];
echo preg_replace(...$params) . " & " . $counted;
// same output as the previous snippet
有关更多信息,以下是一些线索,这些线索进一步解释了此功能以及一些常见的相关错误:(我与以下网站没有任何联系)
答案 6 :(得分:1)
它并不完全漂亮,但有些人可能会这样做。
class NamedArguments {
static function init($args) {
$assoc = reset($args);
if (is_array($assoc)) {
$diff = array_diff(array_keys($assoc), array_keys($args));
if (empty($diff)) return $assoc;
trigger_error('Invalid parameters: '.join(',',$diff), E_USER_ERROR);
}
return array();
}
}
class Test {
public static function foobar($required, $optional1 = '', $optional2 = '') {
extract(NamedArguments::init(get_defined_vars()));
printf("required: %s, optional1: %s, optional2: %s\n", $required, $optional1, $optional2);
}
}
Test::foobar("required", "optional1", "optional2");
Test::foobar(array(
'required' => 'required',
'optional1' => 'optional1',
'optional2' => 'optional2'
));
答案 7 :(得分:1)
您可以通过传递对象而不是数组来保持phpdoc和设置默认值的能力,例如
class FooOptions {
$opt1 = 'x';
$opt2 = 'y';
/* etc */
};
如果您想:
,还可以在函数调用中进行严格的类型检查function foo (FooOptions $opts) {
...
}
当然,您可能会为此设置FooOptions对象的额外详细程度。不幸的是,没有完全免费的旅程。
答案 8 :(得分:1)
通常你不能但我认为有很多方法可以将命名参数传递给PHP函数。我个人用数组中继定义,然后调用我需要传递的内容:
class Test{
public $a = false;
private $b = false;
public $c = false;
public $d = false;
public $e = false;
public function _factory(){
$args = func_get_args();
$args = $args[0];
$this->a = array_key_exists("a",$args) ? $args["a"] : 0;
$this->b = array_key_exists("b",$args) ? $args["b"] : 0;
$this->c = array_key_exists("c",$args) ? $args["c"] : 0;
$this->d = array_key_exists("d",$args) ? $args["d"] : 0;
$this->e = array_key_exists("e",$args) ? $args["e"] : 0;
}
public function show(){
var_dump($this);
}
}
$test = new Test();
$args["c"]=999;
$test->_factory($args);
$test->show();
这里的实例: http://sandbox.onlinephpfunctions.com/code/d7f27c6e504737482d396cbd6cdf1cc118e8c1ff
如果我必须传递10个参数,其中3个是我真正需要的数据,那么通常不会传递给函数
return myfunction(false,false,10,false,false,"date",false,false,false,"desc");
根据我提供的方法,您可以将10个参数中的任何一个设置为数组:
$arr['count']=10;
$arr['type']="date";
$arr['order']="desc";
return myfunction($arr);
我的博客中有一篇文章更详细地解释了这个过程。
http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php
答案 9 :(得分:0)
如果您真的想要,请尝试反射。 并跳过空值。
function getDefaultValueByNull($fn, $inputs) {
$ref = new ReflectionFunction($fn);
$args = array_map(function($p) {
return [
$p->getName(),
$p->isDefaultValueAvailable() ? $p->getDefaultValue() : NULL,
];
}, $ref->getParameters());
foreach($inputs as $i=>$val) { if ($val!==NULL) $args[$i][1] = $val; }
return array_column($args, 1, 0);
}
function sum($a=9, $b) {
extract(getDefaultValueByNull(__FUNCTION__, func_get_args()));
return $a+$b;
}
echo sum(NULL, 1); // 10
答案 10 :(得分:0)
只需使用Drupal使用的关联数组模式。对于可选的默认参数,只需接受一个$options
参数,该参数是一个关联数组。然后使用数组+
运算符设置数组中缺少的任何键。
function foo ($a_required_parameter, $options = array()) {
$options += array(
'b' => '',
'c' => '',
);
// whatever
}
foo('a', array('c' => 'c’s value')); // No need to pass b when specifying c.
答案 11 :(得分:0)
这是一个解决方法:
function set_param_defaults($params) {
foreach($params['default_values'] as $arg_name => $arg_value) {
if (!isset($params[$arg_name])) {
$params[$arg_name] = $arg_value;
}
}
return $params;
}
function foo($z, $x = null, $y = null) {
$default_values = ['x' => 'default value for x', 'y' => 'default value for y'];
$params = set_param_defaults(get_defined_vars());
print "$z\n";
print $params['x'] . "\n";
print $params['y'] . "\n";
}
foo('set z value', null, 'set y value');
print "\n";
foo('set z value', 'set x value');
<强>可替换地:强> 我个人会采用这种方法。
function foo($z, $x_y) {
$x_y += ['x' => 'default value for x', 'y' => 'default value for y'];
print "$z\n";
print $x_y['x'] . "\n";
print $x_y['y'] . "\n";
}
foo('set z value', ['y' => 'set y value']);
print "\n";
foo('set z value', ['x' => 'set x value']);
打印两个例子。
第一个电话:
第二次电话:
答案 12 :(得分:0)
你不能用python方式做到这一点。 Anway,您可以传递一个关联数组,而不是按名称使用数组条目:
function test ($args=array('a'=>'','b'=>'','c'=>''))
{
// do something
}
test(array('c'=>'Hello'));
这不会减少输入,但至少它更具描述性,让参数的名称在调用中可见且可读。
答案 13 :(得分:0)
非常简短,有时是,使用反射和类型变量。但是我认为这可能不是你想要的。
对你的问题更好的解决方案可能是传递3个参数,因为函数自己处理你函数中缺少的一个
<?php
function test(array $params)
{
//Check for nulls etc etc
$a = $params['a'];
$b = $params['b'];
...etc etc
}
答案 14 :(得分:0)
简单的回答。不,你不能 您可以尝试通过传入对象/数组或使用其他一些依赖注入模式来解决它。
此外,尝试使用空值而不是空字符串,因为使用is_null()
测试它们的存在更明确例如:
function test ($a=null,$b=null,$c=null){
if (is_null($a) {
//do something about $a
}
if (is_null($b) {
//do something about $b
}
if (is_null($c) {
//do something about $c
}
}
称之为:
test(null,null,"Hello");
答案 15 :(得分:0)
我不这么认为...... 如果您需要拨打substr功能,其中包含3个参数,并希望设置 $ length 而不设置$ start,则将被迫这样做。
substr($str,0,10);
一种很好的覆盖方法是始终使用数组作为参数
答案 16 :(得分:0)
尝试function test ($a="",$b="",&$c=""){}
将&
放在$c
答案 17 :(得分:0)
不,不是真的。您可以使用它的一些替代方案。
test(null,null,"hello")
或传递数组:
test(array('c' => "hello"));
然后,该功能可以是:
function test($array) {
$c = isset($array[c]) ? $array[c] : '';
}
或者在两者之间添加一个函数,但我不建议这样做:
function ctest($c) { test('','',$c); }
答案 18 :(得分:0)
这是我一直在使用的。函数定义采用一个可选的数组参数,该参数指定可选的命名参数:
function func($arg, $options = Array()) {
$defaults = Array('foo' => 1.0,
'bar' => FALSE);
$options = array_merge($default, $options);
// Normal function body here. Use $options['foo'] and
// $options['bar'] to fetch named parameter values.
...
}
您通常可以在没有任何命名参数的情况下调用:
func("xyzzy")
要指定可选的命名参数,请在可选数组中传递它:
func("xyzzy", Array('foo' => 5.7))