Почему этот вызов функции PHP работает только один раз? - PullRequest
2 голосов
/ 17 января 2010

Я написал простой массив и использовал бы его для печати набора опций списка 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 ]

3 голосов
/ 17 января 2010

Вы должны сбросить указатель массива: используйте reset ()

Но почему бы вам не использовать цикл foreach?

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

И не используйте глобальный, это зло. Объявите массив $ units как статический в теле функции.

3 голосов
/ 17 января 2010

each() увеличивает курсор внутреннего массива. Поскольку $ unit является глобальной переменной, ваш первый вызов unit_select_option () перемещает курсор до конца $ единиц, и там он остается для последующих вызовов.

Вам нужно перемотать массив, используя reset($units); в конце unit_select_option().

PHP Документация: сброс

2 голосов
/ 17 января 2010

С 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;
}

и вы избежите всех этих проблем.

1 голос
/ 17 января 2010

Хорошо, как уже говорили другие, проблема была в том, что вы не сбрасывали глобальный массив.

Однако я бы не захотел использовать глобал, а вместо этого каждый раз передавал его в unit_select_option. (Массивы и объекты передаются по ссылке в последних версиях PHP, поэтому нет причин не делать этого, и это обычно считается лучшей практикой программирования.)

Во-вторых, вы делаете некоторые странные вещи в цикле while - я бы подумал, что итератор foreach будет иметь больше смысла в этом случае:

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

Просто идея. : -)

1 голос
/ 17 января 2010

Другие ответы уже должны были решить ваш вопрос.

Я хочу добавить, что PHP имеет конструкцию foreach, поэтому вместо цикла while вы можете просто написать

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

Вам не нужно reset(), если вы используете foreach.

1 голос
/ 17 января 2010

Вам нужно сбросить ваш массив после или перед вашим блоком while.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...