代码之家  ›  专栏  ›  技术社区  ›  Stefan Gehrig

PHP按引用参数和默认值为null

  •  11
  • Stefan Gehrig  · 技术社区  · 16 年前

    public static function explodeDn($dn, array &$keys = null, array &$vals = null,
        $caseFold = self::ATTR_CASEFOLD_NONE)
    

    我们可以通过省略之后的所有参数来轻松调用该方法 $dn :

    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com');
    

    我们还可以使用3个参数调用该方法:

    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v);
    

    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
        Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);
    

    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, null, 
        Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);
    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', null, $v);
    

    传球和传球有什么区别 null

    6 回复  |  直到 10 年前
        1
  •  27
  •   Tomalak    16 年前

    这是因为不能有对null的引用。

    您可以对包含null的变量进行引用—这正是默认值所做的。或者,您可以将null作为文本值传入—但由于您需要out参数,因此在这里不可能这样做。

        2
  •  11
  •   Szczepan Hołyszewski    12 年前

    如果要显式传递NULL,则必须为by ref参数创建一个伪变量,但不必在单独的行上创建该变量。可以直接将赋值表达式(如$dummy=NULL)用作函数参数:

    function foo (&$ref = NULL) {
    
        if (is_null($ref)) $ref="bar";
        echo "$ref\n";        
    }
    
    foo($dummy = NULL); //this works!
    
        3
  •  5
  •   Rafa    12 年前

    这是我自己发现的,我非常震惊!

    这就是 PHP documentation 说:

    function makecoffee($type = "cappuccino")
    {
        return "Making a cup of $type.\n";
    }
    echo makecoffee(); // returns "Making a cup of cappuccino."
    echo makecoffee(null); // returns "Making a cup of ."
    echo makecoffee("espresso"); // returns "Making a cup of espresso."
    

    我早就料到了 makecoffee(null) 返回“做一杯卡布奇诺”。

    function makecoffee($type = null)
    {
        if (is_null($type)){ 
           $type = "capuccino";
        }
        return "Making a cup of $type.\n";
    }
    

    现在 煮咖啡(空) 返回“制作一杯卡布奇诺”

        4
  •  4
  •   josh    14 年前

    @托马拉克

    实际上,默认值创建的变量没有任何引用。这是当你传球时你根本无法启动的。

    我发现以下示例(我没有测试)可以说明原因:

    function foo (&$ref = NULL) {
      $args = func_get_args();
      echo var_export($ref, TRUE).' - '.var_export($args, TRUE);
    }
    $bar = NULL;
    foo();     // NULL - array()
    foo($bar); // NULL - array(0 => NULL)
    

    在我看来,PHP应该提供一种不传递某些参数的方法,比如
    foo($p1, , , $p4);
    但事实并非如此,因此必须使用虚拟变量。

        5
  •  1
  •   Community SushiHangover    7 年前

    只是为了证实什么 Tomalak 规定的 here :

    以下工作:

    $k=array();
    $v=null;
    $dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
        Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);
    

    不太好,但解释清楚易懂。

        6
  •  1
  •   Community SushiHangover    7 年前

    正如@aschmecher在评论中指出的那样 @Szczepan's answer here ,做 func($var = null) 生成严格的标准通知。

    一个解决方案

    <?php
    error_reporting(E_ALL | E_STRICT);
    
    function doIt(&$x = null) {
        if($x !== null) echo "x not null: $x\n";
        $x = 2;
    }
    
    function &dummyRef() {
        $dummyRef = null;
        return $dummyRef;
    }
    
    doIt(dummyRef());
    
    doIt(dummyRef());
    

    解释

    doIt(dummy()) 是验证引用 $dummy 值未在调用之间持久化。这与显式创建变量形成对比,其中需要记住清除任何累积值:

    $dummyRef = null;
    doIt($dummyRef);
    doIt($dummyRef); // second call would print 'x not null: 2'
    

    在OP的例子中,它是:

    $dn = Zend_Ldap_Dn::explodeDn(
        'CN=Alice Baker,CN=Users,DC=example,DC=com',
        $k,
        dummyRef(),
        Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER
    );
    

    其他考虑事项

    我可能担心的一件事是,这种方法是否会造成内存泄漏。下面的测试表明它没有:

    <?php
    function doItObj(&$x = null) {
        if(gettype($x) !== "object") echo "x not null: $x\n";
        $x = 2;
    }
    
    function &dummyObjRef() {
        $dummyObjRef = new StdClass();
        return $dummyObjRef;
    }
    
    echo "memory before: " . memory_get_usage(true) .  "\n";
    
    for($i = 0; $i < 1000000; $i++) {
        doItObj(dummyObjRef());
    }
    
    echo "memory after: " . memory_get_usage(true) . "\n";
    
    echo "\n$i\n";