Мне нужен необязательный аргумент, который принимает любое значение (в том числе null
а также false
), но все еще имеет «неопределенное» состояние, чтобы разрешить другое поведение «по умолчанию». Есть ли в PHP методика, которая позволяет имитировать «неопределенное» значение?
я хочу добавить append
метод к YaLinqo, мой порт .NET LINQ. В настоящее время код выглядит так:
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;
});
}
Проблема в том, если кто-то хочет использовать null
в качестве ключа они не смогут это сделать, так как в настоящее время это специальное «неопределенное» значение, которое приведет к выдаче с использованием автоматического последовательного целого числа. В PHP итератор, содержащий последовательность [ null => null, null => null ]
совершенно правильно, и пользователь должен иметь возможность производить его, используя append
,
Я подумываю добавить 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;
});
}
Это правильный подход? Есть ли более чистый способ?
Вы могли бы использовать func_get_args()
добиться того, что вы хотите. Взгляните на следующий пример:
function test($value, $key = null) {
var_dump(func_get_args());
}
test(1);
test(2, null);
И вот вывод:
array(1) {
[0]=>
int(1)
}
array(2) {
[0]=>
int(2)
[1]=>
NULL
}
Как видите, список аргументов содержит только переданные аргументы и не определенные аргументы. Если вы хотите знать, если кто-то явно прошел null
ты можешь сделать:
$args = func_get_args();
if (isset($args[1]) && $args[1] === null) {}
Или, если вы хотите знать, что аргумент не был передан, вы можете сделать:
$args = func_get_args();
if (!isset($args[1])) {}
Нет простого способа добиться этого. В вашем случае пользователь все еще может определить $ key с помощью {YaLinqo.Utils.Undefined}
значение и в этом случае будет выполняться неправильная ветвь кода. Я могу думать только об одном решении — мы можем проанализировать кадры стека вызовов, чтобы убедиться, передал ли пользователь какой-либо аргумент или нет. Вот так :
<?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();
?>