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

Как разрешить неоднозначные имена столбцов при получении результатов?

Web

Как сохранить изображение PNG на стороне сервера из URI данных base64

Web

Транзакции в PHP + MySQL

Web

Для laravel требуется расширение Mcrypt PHP

×