为什么这个PHP函数调用只工作一次?

时间:2010-01-17 13:38:47

标签: php arrays

我写了一个简单的数组,我会用它来打印一个带有选定元素的html列表选项集。 如果我尝试在我的页面中打印多个列表,我的问题就开始了,因为只有第一个列表打印正确,为什么?

<?php


$units = array (
'0' => 'Units',
'kJ' => 'Kilojoule: kJ',
'g' => 'Grams: g',
'mg' => 'Milligrams: mg',
'mcg' => 'Micrograms: mcg, µg');

function unit_select_option ($attributes, $code = "") {
    global $units;
    $html = "<select title=\"Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;\" $attributes>\r";

    while (list($key, $name) = each($units)) {
        if ($key == "0") {
            $html .= "  <option title=\"$name\" value='$key'>$name</option>\r";
        } else if ($key == $code) {
            $html .= "  <option title=\"$name\" selected=\"selected\" value='$key'>$key</option>\r"; 
        } else {
            $html .= "  <option title=\"$name\" value='$key'>$key</option>\r";
        }
    }
    $html.= "</select>\r";
    return $html;
}

print unit_select_option ('class="units_select"', "g");
print unit_select_option ('class="units_select"', "mg");
print unit_select_option ('class="units_select"', "mcg");
?>

代码不应该没什么奇怪但是我没有发现问题,因为页面没有返回任何错误。

html code:
<select title="Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;" class="units_select">
    <option title="Unit&agrave;" value='0'>Unit&agrave;</option>
    <option title="Kilojoule: kJ" value='kJ'>kJ</option>
    <option title="Grammi: g" selected="selected" value='g'>g</option>
    <option title="Milligrammi: mg" value='mg'>mg</option>
    <option title="Microgrammi: mcg, µg" value='mcg'>mcg</option>
</select>
<select title="Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;" class="units_select">
</select>
<select title="Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;" class="units_select">
</select>

6 个答案:

答案 0 :(得分:3)

each()推进内部数组游标。因为$ units是一个全局变量,所以你第一次调用unit_select_option()会将光标前进到$ units的末尾,并且它仍然存在于后续调用中。

您需要使用reset($units);末尾的unit_select_option()来回放数组。

PHP文档:reset

答案 1 :(得分:3)

您应该重置数组指针:使用reset()

但为什么不使用foreach循环?

foreach($units as $key => $name){ ... }

不要使用全球,这是邪恶的。在函数体中声明$ units数组为静态。

答案 2 :(得分:2)

来自each()

  

返回当前键和值对   从数组中推进数组   光标。

     

执行each()后,数组   光标将留在下一个   数组的元素,或者超过最后一个元素   元素,如果它击中了结束   阵列。你必须使用reset()   如果你想遍历数组   再次使用每个。

所以:

function unit_select_option ($attributes, $code = "") {
  global $units;
  $html = "<select title=\"Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;\" $attributes>\r";
  reset($units);
  while (list($key, $name) = each($units)) {
    if ($key == "0") {
      $html .= "  <option title=\"$name\" value='$key'>$name</option>\r";
    } else if ($key == $code) {
      $html .= "  <option title=\"$name\" selected=\"selected\" value='$key'>$key</option>\r"; 
    } else {
      $html .= "  <option title=\"$name\" value='$key'>$key</option>\r";
    }
  }
  $html.= "</select>\r";
  return $html;
}

我倾向于避免使用each(),因为它不可重入,这意味着如果在你的循环中你调用了在同一个数组上使用它的其他东西它会影响你的外部调用。不好。你最好只使用foreach循环:

function unit_select_option ($attributes, $code = "") {
  global $units;
  $html = "<select title=\"Kilojoule: kJ;&#13;Grammi: g;&#13;Milligrammi: mg;&#13;Microgrammi: mcg, µg;\" $attributes>\r";
  foreach ($units as $key => $name) {
    if ($key == "0") {
      $html .= "  <option title=\"$name\" value='$key'>$name</option>\r";
    } else if ($key == $code) {
      $html .= "  <option title=\"$name\" selected=\"selected\" value='$key'>$key</option>\r"; 
    } else {
      $html .= "  <option title=\"$name\" value='$key'>$key</option>\r";
    }
  }
  $html.= "</select>\r";
  return $html;
}

你可以避免所有这些问题。

答案 3 :(得分:1)

你需要在你的while块之前或之前reset你的数组。

答案 4 :(得分:1)

其他答案应该已经解决了你的问题。

我想补充一点,PHP有foreach构造,所以不用while循环就可以写

foreach ($unit as $key => $name) {
  ...
}

如果您使用reset(),则无需foreach

答案 5 :(得分:1)

好的,正如其他人所说的那样,问题是因为你没有重置全局数组。

但是,我很想不使用全局,而是每次都将它传递给unit_select_option。 (在最近的PHP版本中,数组和对象通过引用传递,因此没有理由不这样做,并且它通常被认为是更好的编程实践。)

其次,你在while循环中做了一些奇怪的事情 - 我认为foreach迭代器在这个实例中更有意义:

foreach($units as $key => $value)

只是一个想法。 : - )