缺少PHP数组孙子

时间:2011-09-24 10:36:04

标签: php arrays

我有一些用于从PHP构建HTML表的代码。

<?php

function new_table($class)
{
    $table = array('class' => $class, 'tr' => array());

    return $table;
}

function new_tr(&$table, $class)
{
    $tr = array('class' => $class, 'td' => array());

    $table['tr'][] = $tr;

    return $tr;
}

function new_td(&$tr, $class, $content)
{
    $td = array('class' => $class, 'content' => $content);

    $tr['td'][] = $td;

    return $td;
}
?>

用法:

    $table = new_table('admin whoami');

    $tr = new_tr($table, 'head');
    new_td($tr, 'field', 'Field');
    new_td($tr, 'value', 'Value');

    $tr = new_tr($table, 'body');
    new_td($tr, 'field', 'Name');
    new_td($tr, 'value', $my_name);

    echo '--- tr ---'.chr(10);
    var_dump($tr);

    echo '--- table ---'.chr(10);
    var_dump($table);

结果:

--- tr ---
array(2) {
  ["class"]=>
  string(4) "body"
  ["td"]=>
  array(2) {
    [0]=>
    array(2) {
      ["class"]=>
      string(5) "field"
      ["content"]=>
      string(4) "Name"
    }
    [1]=>
    array(2) {
      ["class"]=>
      string(5) "value"
      ["content"]=>
      string(5) "user0"
    }
  }
}
--- table ---
array(2) {
  ["class"]=>
  string(12) "admin whoami"
  ["tr"]=>
  array(2) {
    [0]=>
    array(2) {
      ["class"]=>
      string(4) "head"
      ["td"]=>
      array(0) {
      }
    }
    [1]=>
    array(2) {
      ["class"]=>
      string(4) "body"
      ["td"]=>
      array(0) {
      }
    }
  }
}

如果你注意到,var_dump($ tr)正确地转储了tr,包括子td元素。

然而,var_dump($ table)虽然正确地var_dumping tr元素,但并没有var_dump孙子td元素 - 注意空数组[“td”] =&gt; array(0){}

你知道为什么会这样吗?

它与返回的$ tr元素有关,是$ table ['tr']元素的副本而不是引用吗?在这种情况下,为什么在向tr添加td时,在表中添加tr不起作用?

谢谢!

2 个答案:

答案 0 :(得分:3)

问题在于你的new_tr()函数:

function new_tr(&$table, $class)
{
    $tr = array('class' => $class, 'td' => array());

    $table['tr'][] = $tr;

    return $tr;
}

这里创建$ tr的方式意味着它是一个常规变量,必要时会被复制。它确实被添加到$ table中,因为这是一个参考。

PHP使用copy on write,所以当代码返回$ tr时,你添加到$ table,而你返回的$ tr实际上仍然是同一个变量。

但是当你在new_td()中写入它时,PHP确定它需要复制,因为它不是对某些东西的引用。所以此时你的调用脚本中的$ tr和$ table数组中相应的$ tr实际上是两个独立的变量/值。所以new_td()得到了$ tr的副本,而不是你在new_tr()中创建的那个。

要解决此问题,您需要使new_tr函数实际创建对TR的引用,并返回它作为引用创建的TR:

// Return the created TR as a reference by adding the ampersand here.
function &new_tr(&$table, $class)
{
    $tr = array('class' => $class, 'td' => array());

    // The TR in $table needs to be a reference to the value we're returning 
    // because we want to modify this exact variable instead of some copy.
    $table['tr'][] =& $tr;

    return $tr;
}

现在当你运行它并且你的代码调用new_td($ tr)时,它实际上正在修改你添加到$ table的变量:

$table = new_table('admin whoami');
$tr    =& new_tr($table, 'head');
new_td($tr, 'field', 'Field');

// EDIT: Note how you need to create a reference here aswell. This is to
// make $tr a reference to the return value of new_tr() instead of a value copy.  
$tr =& new_tr($table, 'body');

echo '--- table ---'.chr(10);
var_dump($table);

结果:

--- table ---
array(2) {
  ["class"]=>
  string(12) "admin whoami"
  ["tr"]=>
  array(2) {
    [0]=>
    array(2) {
      ["class"]=>
      string(4) "head"
      ["td"]=>
      array(1) {
        [0]=>
        array(2) {
          ["class"]=>
          string(5) "field"
          ["content"]=>
          string(5) "Field"
        }
      }
    }
    [1]=>
    &array(2) {
      ["class"]=>
      string(4) "body"
      ["td"]=>
      array(0) {
      }
    }
  }
}

答案 1 :(得分:0)

$table['tr'][] = $tr;

此行会将创建的tr添加到数组中,但请注意,一旦返回$tr,它就会过着自己的生命。修改它时,不会在table

中更新该值