С PHP 7.2 each
устарел. В документации говорится:
Предупреждение Эта функция была отключена с PHP 7.2.0. Полагаться на эту функцию крайне не рекомендуется.
Я работаю над адаптацией приложения электронной коммерции и конвертированием всех в while-each
цикл в (предположительно) эквивалент foreach
.
Как вы можете видеть ниже, я уже заменил все циклы reset
& while
эквивалентным foreach
.
Это в основном работало нормально. Тем не менее, у нас был клиент с очень длинным списком предметов в своей тележке, которые пытались проверить и жаловались, что она получает ошибку 502 с сервера. Я попытался воспроизвести это и обнаружил, что только ее тележка терпит неудачу, для загрузки страницы проверки занимает более 2 минут, а затем раз с 502. Затем я начал отлаживать большое количество файлов, которые я недавно изменил, проб и ошибок, до тех пор, пока я выяснили, что проблема связана с этим конкретным файлом и конкретной функцией. Всякий раз, когда я включаю первый foreach
цикл обратно в while
цикл, клиент может загрузить страницу оформления заказа менее чем за секунду. Переключение обратно в foreach
- и снова это займет минуты, но php истекает до завершения выполнения.
Я сделал выполнять тесты, конечно, на выходе этого foreach
против в while
петля (var_dump $products_id
и $this->contents
, например), и все они кажутся одинаковыми. Я уже переписал код, чтобы он работал плавно и оставался совместимым с PHP 7.2, но я до сих пор не могу понять, почему это происходит.
Это полная функция:
function get_content_type() {
$this->content_type = false;
if ( (DOWNLOAD_ENABLED == 'true') && ($this->count_contents() > 0) ) {
// reset($this->contents);
// while (list($products_id, ) = each($this->contents)) {
foreach(array_keys($this->contents) as $products_id) {
if (isset($this->contents[$products_id]['attributes'])) {
// reset($this->contents[$products_id]['attributes']);
// while (list(, $value) = each($this->contents[$products_id]['attributes'])) {
foreach ($this->contents[$products_id]['attributes'] as $value) {
$virtual_check_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS_ATTRIBUTES . " pa, " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad where pa.products_id = '" . (int)$products_id . "' and pa.options_values_id = '" . (int)$value . "' and pa.products_attributes_id = pad.products_attributes_id");
$virtual_check = tep_db_fetch_array($virtual_check_query);
if ($virtual_check['total'] > 0) {
switch ($this->content_type) {
case 'physical':
$this->content_type = 'mixed';
return $this->content_type;
break;
default:
$this->content_type = 'virtual';
break;
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed';
return $this->content_type;
break;
default:
$this->content_type = 'physical';
break;
}
}
}
} elseif ($this->show_weight() == 0) {
// reset($this->contents);
// while (list($products_id, ) = each($this->contents)) {
foreach (array_keys($this->contents) as $products_id) {
$virtual_check_query = tep_db_query("select products_weight from " . TABLE_PRODUCTS . " where products_id = '" . $products_id . "'");
$virtual_check = tep_db_fetch_array($virtual_check_query);
if ($virtual_check['products_weight'] == 0) {
switch ($this->content_type) {
case 'physical':
$this->content_type = 'mixed';
return $this->content_type;
break;
default:
$this->content_type = 'virtual';
break;
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed';
return $this->content_type;
break;
default:
$this->content_type = 'physical';
break;
}
}
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed';
return $this->content_type;
break;
default:
$this->content_type = 'physical';
break;
}
}
}
} else {
$this->content_type = 'physical';
}
return $this->content_type;
}
Спасибо
EDIT: вот массив: https://pastebin.com/VawX3XpW
Проблема была протестирована и воспроизведена во всех конфигурациях, которые я пробовал:
1) Высококачественные окна 10 шт + WAMP (Apache 2.4 + MariaDB 10.2 + PHP 5. 6+/7 +/7. 1+/7. 2+)
2) Высокопроизводительный сервер CentOS/cPanel + Litespeed + MariaDB 10.1 + PHP 5. 6+
Просто чтобы подчеркнуть, я не хочу переписывать код или подражать each
а затем переписывать код, поскольку мы мало что узнаем из этого. Я просто пытаюсь найти логическое объяснение или способ решить/отладить эту тайну. Возможно, кто-то где-то столкнулся с такой проблемой и может пролить свет на это.
ОБНОВЛЕНИЕ 01/авг /2018
Я пытался отлаживать это в течение нескольких дней, в конце концов заметил что-то интересное. Я добавил "эхо-точки" и exit
в первый цикл foreach
while
цикле:
function get_content_type() {
$this->content_type = false;
if ( (DOWNLOAD_ENABLED == 'true') && ($this->count_contents() > 0) ) {
// reset($this->contents);
// while (list($products_id, ) = each($this->contents)) { echo '1 ';
foreach(array_keys($this->contents) as $products_id) { echo '1 ';
if (isset($this->contents[$products_id]['attributes'])) { echo '2 ';
// reset($this->contents[$products_id]['attributes']);
// while (list(, $value) = each($this->contents[$products_id]['attributes'])) {
foreach ($this->contents[$products_id]['attributes'] as $value) { echo '3 ';
$virtual_check_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS_ATTRIBUTES . " pa, " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad where pa.products_id = '" . (int)$products_id . "' and pa.options_values_id = '" . (int)$value . "' and pa.products_attributes_id = pad.products_attributes_id");
$virtual_check = tep_db_fetch_array($virtual_check_query);
if ($virtual_check['total'] > 0) {
switch ($this->content_type) {
case 'physical':
$this->content_type = 'mixed'; echo '4 ';
return $this->content_type;
break;
default:
$this->content_type = 'virtual'; echo '5 ';
break;
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed'; echo '6 ';
return $this->content_type;
break;
default:
$this->content_type = 'physical'; echo '7 ';
break;
}
}
}
} elseif ($this->show_weight() == 0) {
// reset($this->contents);
// while (list($products_id, ) = each($this->contents)) {
foreach (array_keys($this->contents) as $products_id) {
$virtual_check_query = tep_db_query("select products_weight from " . TABLE_PRODUCTS . " where products_id = '" . $products_id . "'");
$virtual_check = tep_db_fetch_array($virtual_check_query);
if ($virtual_check['products_weight'] == 0) {
switch ($this->content_type) {
case 'physical':
$this->content_type = 'mixed'; echo '8 ';
return $this->content_type;
break;
default:
$this->content_type = 'virtual'; echo '9 ';
break;
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed'; echo '10 ';
return $this->content_type;
break;
default:
$this->content_type = 'physical'; echo '11 ';
break;
}
}
}
} else {
switch ($this->content_type) {
case 'virtual':
$this->content_type = 'mixed'; echo '12 ';
return $this->content_type;
break;
default:
$this->content_type = 'physical'; echo '13 ';
break;
}
}
} exit; //Exiting from the loop to check output
} else {
$this->content_type = 'physical';
}
return $this->content_type;
}
Когда я работал с циклом while
, вывод, который я получил, был всего лишь "1 13" один раз, что означает, что цикл работает только один раз и останавливается. Однако, когда я изменил его на foreach
, у меня появился длинный список "1 13 1 13 1 13...", то есть он многократно зацикливался. Я пошел дальше исследовать, если есть какая-либо разница между breaks
циклов while
и foreach
, и я до сих пор не нашел никакой вспомогательной информации. Затем я переписал последний break;
break 2;
и протестировали foreach
снова и на этот раз он, кажется, был запущен только один раз, так же, как когда он был в while
петля с break;
(не break 2;
) РЕДАКТИРОВАТЬ: просто уточнить - нет разницы между break
и break
. Они работают одинаково.
UPDATE # 2: я пересмотрел } elseif ($this->show_weight() == 0) {
к } elseif (2 == 0) {
и в while
цикл в настоящее время работает как много раз, как foreach
цикла. var_dump($this->show_weight());
результаты float 4466.54
. Вопрос до сих пор не имеет для меня никакого смысла.
еще раз спасибо