如何确定是否设置了pass-by-reference变量?

时间:2012-10-28 16:26:21

标签: php

对于声明如下的任意函数:

function foo($first, &$second = null) {
    // if ($second is assigned) {
    //     Work with $second
    // }
}

如何在呼叫时确定$second是否确实分配给变量,例如:

foo('hello', $second);

VS

foo('hello'); // Notice &$second is unassigned

尝试isset()is_null(),但它们似乎无效。

更新

在这里创建了test script here

4 个答案:

答案 0 :(得分:3)

我的理解是你希望实现一个实现类似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前添加参数时;然而,自然这不应该经常发生,因为它肯定会破坏依赖功能。最后添加更多参数对上面的代码没有影响。

有两种方法可以解决这个问题:

  1. ReflectionFunction - 开发人员的新玩具,它允许您内省您的功能,并确定签名是否从创建时更改。尽管如此,谨慎使用它,内省并不便宜,特别是考虑到替代品。

  2. 简陋的代码评论 - 低调的代码监管形式;一条简单的行,上面写着// IMPORTANT - don't add arguments before $second

答案 1 :(得分:1)

你不能(据我所知)使用isset告诉NULL和Undefined之间的区别。您可以将$ second的默认值设置为一些永远不会使用的随机值。

define('UNDEFINED', -19181818);

function foo($first, &$second = UNDEFINED) 
{
 if($second==UNDEFINED)
 {
  etc..
 }
}

答案 2 :(得分:1)

Works for me

<?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
     ^^^^^       ^^^^

这正是我所期望的,即您可以在此使用issetis_null

答案 3 :(得分:1)

我认为Jack使用func_num_args()的建议非常好。

function foo($first, &$second = null) {
    if (func_num_args() > 1) {
        //$second MUST be assigned
    }
}

这正确地检测何时$second引用调用范围符号表中存在的变量,但它的变量值为null。

$second = null;
foo('hello', $second);