How can I update code that uses the deprecated each() function?
-
For your first two example cases, you could use
key()
andcurrent()
to assign the values you need.$ar = $o->me; // reset isn't necessary, since you just created the array $typ = key($ar); $val = current($ar);
-
$out = array('me' => array(), 'mytype' => 2, '_php_class' => null); $expected = [key($out), current($out)];
In those cases, you can use
next()
to advance the cursor afterward, but it may not be necessary if the rest of your code doesn't depend on that. -
For the third case, I'd suggest just using a
foreach()
loop instead and assigning$kv
inside the loop.foreach ($broken as $k => $v) { $kv = [$k, $v]; }
-
For the fourth case, it looks like the key is disregarded in
list()
, so you can assign the current value.$this->result = current($this->cache_data);
Like the first two cases, it may be necessary to advance the cursor with
next()
depending on how the rest of your code interacts with$this->cache_data
. -
Fifth can be replaced with a
for()
loop.reset($array); for ($i = 0; $i < 30; $i++) { $id = key($array); $item = current($array); // code next($array); }
2019+ Instant Upgrade of each()
Checkout live demo for each each
migration
There are actually plenty of cases that each()
can be replaced, that's why there are so many different upvoted answers in this question.
-while (list($key, $callback) = each($callbacks)) {
+foreach ($callbacks as $key => $callback) {
// ...
}
And:
-while (list($key) = each($callbacks)) {
+foreach (array_keys($callbacks) as $key) {
// ...
}
You can replace one by one manually. But isn't there a better way?
I help to migrate projects, where are over 150+ cases like this. I'm lazy so I made a tool called Rector, that converts the code the way above (+ there are more cases, but I don't want to spam the answer).
It's part of the PHP_72
set.
4 Steps to Upgrade your Code
1. Install it
composer require rector/rector --dev
2. Create rector.php
config
vendor/bin/rector init
3. Add PHP_72
set
<?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. Run it on your code
vendor/bin/rector process src --set php72
I hope it helps you with your migration.
If there is some bug or anomaly, it's Rector missed case. Create an issue, so we can fix it and make it work for every case possible.
I found a way to fix it and thought to share the information. Here are also other cases about how to upgrade each() loops to foreach().
Case 1: Missing $value
reset($array);
while (list($key, ) = each($array)) {
Update to:
foreach(array_keys($array) as $key) {
Case 2: Missing $key
reset($array);
while (list(, $value) = each($array)) {
Update to:
foreach($array as $value) {
Case 3: Not missing anything
reset($array);
while (list($key, $value) = each($array)) {
Update to:
foreach($array as $key => $value) {
you could create your own each()
function using key(), current() and next(). then replace your calls with that function, like this:
<?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);) {...}
reset($array);
while (list($key, $value) = each($array)) {
UPDATE
reset($array);
foreach($array as $key => $value) {