Reputation: 34285
I need an optional argument that accepts any value (including null
and false
), but still has "unspecified" state to allow a different "default" behavior. Is there any technique in PHP which allows imitating "undefined" value?
I want to add append
method to YaLinqo, my port of .NET's LINQ. Currently the code looks like this:
public function append ($value, $key = null)
{
return new self(function () use ($value, $key) {
foreach ($this as $k => $v)
yield $k => $v;
if ($key !== null)
yield $key => $value;
else
yield $value;
});
}
The problem is, if somebody wants to use null
as a key, they won't be able to do it, as it's a special "undefined" value currently, which will cause yielding using automatic sequental integer. In PHP, iterator containing sequence [ null => null, null => null ]
is perfectly valid and user should be able to produce it using append
.
I'm considering adding const UNDEFINED = '{YaLinqo.Utils.Undefined}'
:
const UNDEFINED = '{YaLinqo.Utils.Undefined}';
public function append ($value, $key = Utils::UNDEFINED)
{
return new self(function () use ($value, $key) {
foreach ($this as $k => $v)
yield $k => $v;
if ($key !== Utils::UNDEFINED)
yield $key => $value;
else
yield $value;
});
}
Is this a valid approach? Is there a cleaner way?
Upvotes: 3
Views: 1189
Reputation: 3967
You could use func_get_args()
to achieve what you want. Take a look at the following example:
function test($value, $key = null) {
var_dump(func_get_args());
}
test(1);
test(2, null);
And here is the output:
array(1) {
[0]=>
int(1)
}
array(2) {
[0]=>
int(2)
[1]=>
NULL
}
As you can see the argument list only contains passed in arguments and not defined arguments. If you want to know if someone explicitly passed null
you can do:
$args = func_get_args();
if (isset($args[1]) && $args[1] === null) {}
Or if you want to know the argument was not passed you can do:
$args = func_get_args();
if (!isset($args[1])) {}
Upvotes: 4
Reputation: 11267
No simple way to achieve this. In your case user still can define $key with {YaLinqo.Utils.Undefined}
value and in that case incorrect code branch will execute. I can only think of one solution - we can analyze call stack frames to be sure if user passed some argument or not. Like so :
<?php
function test() {
func(1, null);
func(1);
}
function func ($x, $y = null) {
$stack = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1);
if (count($stack[0]['args']) == 2)
echo "\$y argument is defined\n";
else
echo "\$y argument is UNDEFINED\n";
}
test();
?>
Upvotes: 0