可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am confused about default values for PHP functions. Say I have a function like this:
function foo($blah, $x = "some value", $y = "some other value") {
// code here!
}
What if I want to use the default argument for $x and set a different argument for $y?
I have been experimenting with different ways and I am just getting more confused. For example, I tried these two:
foo("blah", null, "test");
foo("blah", "", "test");
But both of those do not result in a proper default argument for $x. I have also tried to set it by variable name.
foo("blah", $x, $y = "test");
I fully expected something like this to work. But it doesn't work as I expected at all. It seems like no matter what I do, I am going to have to end up typing in the default arguments anyway, every time I invoke the function. And I must be missing something obvious.
回答1:
I would propose changing the function declaration as follows so you can do what you want:
function foo($blah, $x = null, $y = null) {
if (null === $x) {
$x = "some value";
}
if (null === $y) {
$y = "some other value";
}
code here!
}
This way, you can make a call like foo('blah', null, 'non-default y value');
and have it work as you want, where the second parameter $x
still gets its default value.
With this method, passing a null value means you want the default value for one parameter when you want to override the default value for a parameter that comes after it.
As stated in other answers,
default parameters only work as the last arguments to the function.
If you want to declare the default values in the function definition,
there is no way to omit one parameter and override one following it.
If I have a method that can accept varying numbers of parameters, and parameters of varying types, I often declare the function similar to the answer shown by Ryan P.
Here is another example (this doesn't answer your question, but is hopefully informative:
public function __construct($params = null)
{
if ($params instanceof SOMETHING) {
// single parameter, of object type SOMETHING
} else if (is_string($params)) {
// single argument given as string
} else if (is_array($params)) {
// params could be an array of properties like array('x' => 'x1', 'y' => 'y1')
} else if (func_num_args() == 3) {
$args = func_get_args();
// 3 parameters passed
} else if (func_num_args() == 5) {
$args = func_get_args();
// 5 parameters passed
} else {
throw new InvalidArgumentException("Could not figure out parameters!");
}
}
回答2:
Optional arguments only work at the end of a function call. There is no way to specify a value for $y in your function without also specifying $x. Some languages support this via named parameters (VB/C# for example), but not PHP.
You can emulate this if you use an associative array for parameters instead of arguments -- i.e.
function foo(array $args = array()) {
$x = !isset($args['x']) ? 'default x value' : $args['x'];
$y = !isset($args['y']) ? 'default y value' : $args['y'];
...
}
Then call the function like so:
foo(array('y' => 'my value'));
回答3:
It is actually possible:
foo( 'blah', (new ReflectionFunction('foo'))->getParameters()[1]->getDefaultValue(), 'test');
Whether you would want to do so is another story :)
UPDATE:
The reasons to avoid this solution are:
- it is (arguably) ugly
- it has an obvious overhead.
- as the other answers proof, there are alternatives
But it can actually be useful in situations where:
About the performance, a very simple test shows that using the Reflection API to get the default parameters makes the function call 25 times slower, while it still takes less than one microsecond. You should know if you can to live with that.
Of course, if you mean to use it in a loop, you should get the default value beforehand.
回答4:
function image(array $img)
{
$defaults = array(
'src' => 'cow.png',
'alt' => 'milk factory',
'height' => 100,
'width' => 50
);
$img = array_merge($defaults, $img);
/* ... */
}
回答5:
The only way I know of doing it is by omitting the parameter. The only way to omit the parameter is to rearrange the parameter list so that the one you want to omit is after the parameters that you HAVE to set. For example:
function foo($blah, $y = "some other value", $x = "some value")
Then you can call foo like:
foo("blah", "test");
This will result in:
$blah = "blah";
$y = "test";
$x = "some value";
回答6:
You can't do this directly, but a little code fiddling makes it possible to emulate.
function foo($blah, $x = false, $y = false) {
if (!$x) $x = "some value";
if (!$y) $y = "some other value";
// code
}
回答7:
I recently had this problem and found this question and answers. While the above questions work, the problem is that they don't show the default values to IDEs that support it (like PHPStorm).
if you use null
you won't know what the value would be if you leave it blank.
The solution I prefer is to put the default value in the function definition also:
protected function baseItemQuery(BoolQuery $boolQuery, $limit=1000, $sort = [], $offset = 0, $remove_dead=true)
{
if ($limit===null) $limit =1000;
if ($sort===null) $sort = [];
if ($offset===null) $offset = 0;
...
The only difference is that I need to make sure they are the same - but I think that's a small price to pay for the additional clarity.
回答8:
This is case, when object are better - because you can set up your object to hold x and y , set up defaults etc.
Approach with array is near to create object ( In fact, object is bunch of parameters and functions which will work over object, and function taking array will work over some bunch ov parameters )
Cerainly you can always do some tricks to set null or something like this as default
回答9:
You can also check if you have an empty string as argument so you can call like:
foo('blah', "", 'non-default y value', null);
Below the function:
function foo($blah, $x = null, $y = null, $z = null) {
if (null === $x || "" === $x) {
$x = "some value";
}
if (null === $y || "" === $y) {
$y = "some other value";
}
if (null === $z || "" === $z) {
$z = "some other value";
}
code here!
}
It doesn't matter if you fill null
or ""
, you will still get the same result.
回答10:
<?php
function info($name="George",$age=18) {
echo "$name is $age years old.<br>";
}
info(); // prints default values(number of values = 2)
info("Nick"); // changes first default argument from George to Nick
info("Mark",17); // changes both default arguments' values
?>