【问题标题】:PHP - Make reference parameter optional?PHP - 使参考参数可选?
【发布时间】:2013-05-19 16:13:50
【问题描述】:

假设我在 PHP 中定义了一个函数,最后一个参数是通过引用传递的。有什么办法可以让它成为可选的吗?如何判断它是否已设置?

我从来没有在 PHP 中使用过引用传递,所以下面可能会有一个愚蠢的错误,但这里有一个例子:

$foo;
function bar($var1,&$reference)
{
    if(isset($reference)) do_stuff();
    else return FALSE;
}

bar("variable");//reference is not set
bar("variable",$foo);//reference is set

【问题讨论】:

    标签: php


    【解决方案1】:

    取自PHP official manual:

    NULL可以作为默认值,但不能从外部传入

    <?php
    
    function foo(&$a = NULL) {
        if ($a === NULL) {
            echo "NULL\n";
        } else {
            echo "$a\n";
        }
    }
    
    foo(); // "NULL"
    
    foo($uninitialized_var); // "NULL"
    
    $var = "hello world";
    foo($var); // "hello world"
    
    foo(5); // Produces an error
    
    foo(NULL); // Produces an error
    
    ?>
    

    【讨论】:

    • 看看@Michal Lohniský comment。他对 NULL 有很好的洞察力。
    • 我知道这是一个老问题,但是对于那些将来会看到这个答案的人来说, foo(5) 和 foo(NULL) 会抛出错误,因为只有 VARIABLES 可以通过引用传递( 5和 NULL 不是变量)
    • 需要注意的一点是,调用者可以使用值为null 的变量调用函数。因此,如果引用变量纯粹用作输出变量,则无需检查它是否为 null - 如果变量在调用函数之前包含 null,则这样做可能会导致意外行为。
    【解决方案2】:

    你可以通过给它们一个默认值来使参数可选:

    function bar($var1, &$reference = null)
    {
        if($reference !== null) do_stuff();
        else return FALSE;
    }
    

    但是请注意,通过引用传递通常是不好的做法。如果突然我的$foo 的值发生了变化,我必须找出原因只是为了发现它是通过引用传递的。所以请只在你有一个有效的用例时使用它(相信我最没有)。

    还请注意,如果 $reference 应该是一个对象,您可能 don't have to(也不应该)通过引用传递它。

    目前您的函数正在返回不同类型的值。当引用被传递时,它返回null,否则返回false。

    【讨论】:

    • 如果不是因为“[...] 对象默认通过引用传递”,我会赞成,这可以进一步澄清。 blog.golemon.com/2007/01/youre-being-lied-to.html
    • @PleaseStand 我说的是它在用户领域的表现。我可以开始谈论参考计数等,但我认为这只会混淆 OP
    • 我已经编辑了您的帖子以添加指向 PHP 文档的链接,其中没有提到“引用计数”。如果您认为更改不够清晰,请随时恢复更改。
    • @user1363115 如果你真的想了解它是如何工作的,我建议你看这个:blog.ircmaxell.com/2012/12/…
    • 引用:However please note that passing by reference is bad practice in general. 你会说使用preg_match() 通常是不好的做法吗?
    【解决方案3】:

    反应@Martin Perry's post,可以区分

    foo(); // "NULL"
    

    和

    foo($uninitialized_var); // "NULL"
    

    使用func_num_args()

    【讨论】:

      【解决方案4】:

      你可以设置默认值

      $foo;
      function bar($var1,&$reference = false)
      {
          if($reference != false) do_stuff();
           else return FALSE;
      }
      
      bar("variable");//reference is not set
      bar("variable",$foo);//reference is set
      

      【讨论】:

        【解决方案5】:

        试试

        use function bar($var1,&$reference=null)
        {
            if(isset($reference)) do_stuff();
            else return FALSE;
        }
        

        如果您将值传递给 &$reference,它将采用该值。否则为空。

        【讨论】:

          【解决方案6】:

          两种选择:

          声明一个默认值,它在常规值范围之外,例如-1

          function bar($var1,&$reference = -1)
          {
              if($reference !== -1) do_stuff();
              else return FALSE;
          }
          

          不声明参数,检查func_get_args()是否通过:

          function bar($var1)
          {
              if(count(func_get_args()) > 1) do_stuff();
              else return FALSE;
          }
          

          但请注意,第二种方法会触发已弃用的警告:Call-time pass-by-reference has been deprecated;

          【讨论】:

            【解决方案7】:

            以下代码 sn-p 说明引用只是变量名的别名:

            <?php
            function set_variable(&$var, $val)
            {
              $var = $val;
            }
            
            set_variable($b, 2);
            echo $b; // 2
            ?>
            

            Larry Ullman 的 article 解释了按引用传递变量与按值传递的基础知识。

            有趣的是,Larry 文章的末尾有一个指向另一个 article 的链接,该链接深入解释了 PHP 中引用和变量的基础。

            总而言之,当通过提供默认值使引用参数成为可选时,PHP 会“创建”一个新变量来保存默认值,以防我们没有为可选参数提供值。但是,如果我们确实提供了一个,我们必须提供一个变量,其引用参数只是一个别名。

            【讨论】:

              【解决方案8】:

              通过引用传递对于分配非常有用,有时您不需要检查值是否为null。这将允许不加选择地为变量赋值,包括未初始化的变量。

              function f(&$ref = null) {
                  $ref = 1234;
              }
              
              f($x);
              echo $x; // 1234
              f(); // No error
              

              在这样的代码中很有用:

              if (doSomething($value, $errorMessage) === false) {
                  logError($errorMessage);
              }
              
              doSomething($value); // Explicitly ignore error message
              

              【讨论】:

                猜你喜欢
                • 2022-06-15
                • 2014-11-10
                • 2019-02-03
                • 1970-01-01
                • 2013-06-05
                • 1970-01-01
                • 2017-10-18
                • 2012-10-06
                • 1970-01-01
                相关资源
                最近更新 更多