Как определить, установлена ли переменная pass-by-reference?
Для произвольной функции, объявленной следующим образом:
function foo($first, &$second = null) {
// if ($second is assigned) {
// Work with $second
// }
}
Как определить, действительно ли $second
присваивается переменной во время вызова, например.:
foo('hello', $second);
против
foo('hello'); // Notice &$second is unassigned
Пробовал isset()
, is_null()
, но они, похоже, не работают.
Обновление:
Создал test script здесь здесь
Ответы
Ответ 1
Я понимаю, что вы хотите реализовать функцию, которая реализует нечто вроде preg_match
, посредством чего третий аргумент заполняется патчами памяти, если они переданы.
Внутренне функции PHP используют функцию под названием zend_parse_parameters()
; он принимает строку формата и переменное количество аргументов, которые будут заполнены метаданными параметров вызова. Если параметр не передан (например, когда он является необязательным), метаданные недоступны и поэтому легко обнаружить.
Возвращаясь к самому PHP, к сожалению, нет такой вещи, как func_arg_used($var)
, которая сообщит вам, был ли $var
передан как аргумент функции; возможно, это будет интересным вкладом в язык, но до тех пор вам придется довольствоваться чем-то более древним:)
if (func_num_args() > 1) {
// $second was passed and can be used to populate
}
Возможно, вам придется проявлять осторожность при изменении сигнатуры функции, особенно когда вы добавляете параметры перед $second
; однако, естественно, это не должно происходить часто, потому что это наиболее определенно нарушит зависимые функции. Добавление дополнительных аргументов в конец не влияет на код выше.
Есть два способа сделать это:
-
ReflectionFunction
- блестящая новая игрушка разработчиков, она позволяет вам исследовать вашу функцию и определять, изменилась ли подпись с когда он был создан. Используйте его экономно, хотя, самоанализ не дешев, особенно учитывая альтернативу.
-
Смиренный комментарий к коду - очень заниженная форма управления кодом; простая строка, в которой говорится // IMPORTANT - don't add arguments before $second
Ответ 2
Вы не можете (насколько я знаю) рассказать разницу между NULL и Undefined с помощью isset. Вы можете установить значение по умолчанию $second для некоторого случайного значения, которое никогда не будет использоваться иначе.
define('UNDEFINED', -19181818);
function foo($first, &$second = UNDEFINED)
{
if($second==UNDEFINED)
{
etc..
}
}
Ответ 3
Работает для меня:
<?php
function bool_str($b)
{
return ($b ? "true" : "false");
}
function foo($first, &$second = null)
{
echo bool_str(isset($first)) . " " . bool_str(isset($second)) . " " .
bool_str(is_null($first)) . " " . bool_str(is_null($second)) . "\n";
}
$a = 1;
$b = 2;
foo($a, $b);
foo($a);
?>
Вывод:
true true false false
true false false true
^^^^^ ^^^^
Это именно то, чего я ожидал бы, т.е. здесь можно использовать как isset
, так и is_null
.
Ответ 4
Я думаю, что предложение Джека использовать func_num_args() отлично.
function foo($first, &$second = null) {
if (func_num_args() > 1) {
//$second MUST be assigned
}
}
Это правильно определяет, когда $second
ссылается на переменную, которая существует в таблице символов вызывающих областей, но имеет значение переменной null.
$second = null;
foo('hello', $second);