Web

Как я могу обновить код, в котором используется устаревшая функция each()

Использовать в PHP 7.2 функцию each  не рекомендуется. В документации говорится:

Предупреждение: Эта функция УСТАРЕЛА, начиная с PHP 7.2.0. Полагаться на эту функцию крайне не рекомендуется.

 Как я могу обновить свой код, чтобы не использовать ее? Вот некоторые примеры:

$ar = $o->me;

reset($ar);

list($typ, $val) = each($ar);

 

$out = array('me' => array(), 'mytype' => 2, '_php_class' => null);

$expected = each($out);

 

for(reset($broken);$kv = each($broken);) {...}

 

list(, $this->result) = each($this->cache_data);

 

// итерация до конца массива или до предела > длины массива

$i = 0;

reset($array);

while( (list($id, $item) = each($array)) || $i < 30 ) {

    // некоторый код

    $i++;

}

Когда я выполняю этот код на PHP 7.2, я получаю следующую ошибку:

Устарело: функция each() устарела. Это сообщение будет подавлено при дальнейших вызовах.

 

Ответ 1

  1. Для первых двух примеров вы можете использовать функции key() и current() для присвоения нужных вам значений.

$ar  = $o->me;   // сброс не нужен, так как вы только что создали массив

$typ = key($ar);

$val = current($ar);

$out = array('me' => array(), 'mytype' => 2, '_php_class' => null);

$expected = [key($out), current($out)];

В этих случаях вы можете использовать next() для перемещения курсора, но это может быть необязательно, если остальная часть вашего кода не зависит от этого.

  1. В третьем случае я бы предложил foreach()  вместо тогочтобы использовать цикл и назначать $kv внутри цикла.

foreach ($broken as $k => $v) {

     $kv = [$k, $v];

}

  1. В четвертом случае – похоже, что ключ не учитывается в list(), поэтому вы можете присвоить текущее значение.

$this->result = current($this->cache_data);

 

Как и в первых двух случаях, может потребоваться переместить курсор в next() в зависимости от того, как остальная часть вашего кода взаимодействует с $this->cache_data.

  1. Пятый пример можно заменить на цикл for().

reset($array);

for ($i = 0; $i < 30; $i++) {

    $id = key($array);

    $item = current($array);

    // некоторый код

    next($array);

}

 

Ответ 2

На самом деле существует множество случаев, когда each() может быть заменен, вот почему существует огромное количество вариантов.

-while (list($key, $callback) = each($callbacks)) {

+foreach ($callbacks as $key => $callback) {

     // ...

 }

Или:

-while (list($key) = each($callbacks)) {

+foreach (array_keys($callbacks) as $key) {

     // ...

 }

 

Я сделал инструмент под названием Rector, который преобразует код так, как описано выше (+ есть еще больше случаев).

4 шага по обновлению кода

1. Установка пакета

composer require rector/rector --dev

 

2. Создайте конфиг rector.php.

vendor/bin/rector init

 

3. Добавьте набор PHP_72

<?php

use Rector\Core\Configuration\Option;

use Rector\Set\ValueObject\SetList;

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {

    $parameters->set(Option::SETS, [

        Setlist::PHP_72,

    ]);

};

4. Запустите его в своем коде.

vendor/bin/rector process src --set php72

 Надеюсь, это поможет вам.

 

Ответ 3

Я нашел способ исправить это и решил поделиться информацией. Здесь также приведены другие примеры того, как модернизировать циклы each() в foreach(). 

Случай 1: Отсутствует $value 

reset($array);

while (list($key, ) = each($array)) {

Обновляется до:

foreach(array_keys($array) as $key) {

Случай 2: Отсутствует $key 

reset($array);

while (list(, $value) = each($array)) {

 

Обновляется до:

foreach($array as $value) {

Случай 3: Ничего не пропущено

reset($array);

while (list($key, $value) = each($array)) {

 

Обновляется до:

foreach($array as $key => $value) {

 

Ответ 4

Вы можете создать свою собственную функцию each(), используя key(), current() и next(). Затем замените свои вызовы этой функцией, например, так:

<?php

function myEach(&$arr) {

    $key = key($arr);

    $result = ($key === null) ? false : [$key, current($arr), 'key' => $key, 'value' => current($arr)];

    next($arr);

    return $result;

}

Применение:

1.

$ar = $o->me;

reset($ar);

list($typ, $val) = myEach($ar);

 

2.

$out = array('me' => array(), 'mytype' => 2, '_php_class' => null);

$expected = myEach($out);

 

3.

for(reset($broken);$kv = myEach($broken);) {...}

 

Ответ 5

Вот несколько способов сделать это:

Стандартный цикл foreach:

foreach($this->contents as list($products_id)) {

    $total_items += $this->get_quantity($products_id);

}

Или:

$total_items = array_reduce($this->contents, function($acc, $item) {

    return $acc + $this->get_quantity($products_id[0]);

});

 

Или в функциональном исполнении:

$total_items = array_sum(array_map([$this, 'get_quantity'],

                         array_column($this->contents, 0)));

Ни одному из этих методов не нужен reset($this->contents);, предшествующий данным примерам.

 

Ответ 6

То, что вы точно не должны делать, это поместить функцию «обратно в php», добавив ее в параметр auto_prepend_file в php.ini:

auto_prepend_file = "/var/www/php/auto_prepend.php"

Затем создайте файл и введите в него функцию с оберткой function_exists.

<?php

/**

* Добавляет устаревшую функцию each() обратно в 7.2

 */

if (!function_exists('each')) {

    function each($arr) {

        $key = key($arr);

        $result = ($key === null) ? false : [$key, current($arr), 'key' => $key, 'value' => current($arr)];

        next($arr);

        return $result;

    }

}

По сути, это объявляет функцию до запуска вашего php-приложения. Когда ваше приложение попытается запустить каждую функцию, вместо нее будет использована ваша версия.

Это абсолютно не тот способ, с помощью которого вы должны подходить к этой проблеме, особенно в производственном коде! Однако, если вы разработчик с ограничениями по времени и просто хотите попробовать произвольные фреймворки для своего следующего проекта, а они не были обновлены для работы на вашем локальном сервере разработки без отката до вашей версии php, и  если вы приняли на себя обязательства по кодовой базе для вашего проекта, пожалуйста, идите вперед и внедряйте изменения в принятом ответе, потому что они действительно работают.

 

Схожие статьи

Web

Преобразование массива php в Javascript

Сравнение VPN-сервисов: выбираем лучший по нескольким критериям
Web

Сравнение VPN-сервисов: выбираем лучший по нескольким критериям

Что такое ДНС-сервер: расшифровываем термин простыми словами
Web

Что такое ДНС-сервер: расшифровываем термин простыми словами

Web

Изменение максимального размера загружаемого файла