How to Update Code That Uses the Deprecated Each() Function

How can I update code that uses the deprecated each() function?

  1. For your first two example cases, you could use key() and current() 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);

  2. $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.

  3. 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];
    }
  4. 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.

  5. 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);
    }

How to update code that uses deprecated each()

As a general rule, if you need to move away from each($ar) you can usually use [key($ar),current($ar)] as a drop in replacement but then you need to move the pointer within the loop. You usually just need to call next($ar) within the loop and break once you run out of reading room such as breaking when the key is null. Then just make sure the array becomes set to false when it runs out of room.

This type of approach can get ugly very quickly though due to the extra code...

So without really paying much attention to your code, after this update, your revised code would like look:

function get_menu_html($lang, $root_id = 0 )
{
$this->html = array();
$this->items = $this->get_menu_items($lang);

foreach ( $this->items as $item )
$children[$item['sectionParentID']][] = $item;

// loop will be false if the root has no children (i.e., an empty menu!)
$loop = !empty( $children[$root_id] );

// initializing $parent as the root
$parent = $root_id;
$parent_stack = array();

// HTML wrapper for the menu (open)
$this->html[] = '<ul>';

while ( $loop && ( ( $option = [key($children[$parent]),current($children[$parent])] ) || ( $parent > $root_id ) ) )
{
if($option[0] === null){$option = false;} // replicate each's behavior for after last element
next($children[$parent]);
if ( $option === false )
{
$parent = array_pop( $parent_stack );

// HTML for menu item containing children (close)
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 ) . '</ul>';
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ) . '</li>';
break;
}
elseif ( !empty( $children[$option['value']['sectionID']] ) )
{
$tab = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 );

// HTML for menu item containing children (open)
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a>',
$tab, // %1$s = tabulation
$option['value']['sectionPage'], // %2$s = sectionPage (URL)
$option['value']['sectionLabel'] // %3$s = title
);
$this->html[] = $tab . "\t" . '<ul class="submenu">';

array_push( $parent_stack, $option['value']['sectionParentID'] );
$parent = $option['value']['sectionID'];
}
else
// HTML for menu item with no children (aka "leaf")
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a></li>',
str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ), // %1$s = tabulation
$option['value']['sectionPage'], // %2$s = sectionPage (URL)
$option['value']['sectionLabel'] // %3$s = title
);
}

edit: note the above code doesn't work since it references $option['value'] from the each rather than $option[1] from the each. Will need to adjust that in the code.

You might also want to refactor the code. But getting it working, without the deprecated code, is a good first step.

This type of approach is usually very ugly though. Best to refactor and use a foreach loop of some sort specific to the code's logic.

Edit:

Here's an isolated example I'm working on from the link that was provided to the original code:

<?php

/**
* Generate HTML for multi-dimensional menu from MySQL database
* with ONE QUERY and WITHOUT RECURSION
* @author J. Bruni
*/
class MenuBuilder
{

/**
* Menu items
*/
var $items = array();

/**
* HTML contents
*/
var $html = array();



/**
* Get all menu items from database
*/
function get_menu_items()
{
// Change the field names and the table name in the query below to match tour needs
return [
['id'=>1, 'parent_id'=>0, 'title'=>'title 1','link'=>'link 1','position'=>'0'],
['id'=>2, 'parent_id'=>1, 'title'=>'title 2','link'=>'link 2','position'=>'0'],
['id'=>3, 'parent_id'=>1, 'title'=>'title 3','link'=>'link 3','position'=>'0'],
['id'=>4, 'parent_id'=>0, 'title'=>'title 4','link'=>'link 4','position'=>'0'],
];
}

/**
* Build the HTML for the menu
*/
function get_menu_html( $root_id = 0 )
{
$this->html = array();
$this->items = $this->get_menu_items();

foreach ( $this->items as $item )
$children[$item['parent_id']][] = $item;

// loop will be false if the root has no children (i.e., an empty menu!)
$loop = !empty( $children[$root_id] );

// initializing $parent as the root
$parent = $root_id;
$parent_stack = array();

// HTML wrapper for the menu (open)
$this->html[] = '<ul>';

while ( $loop && ( ( $option = each( $children[$parent] ) ) || ( $parent > $root_id ) ) )
{
if ( $option === false )
{
$parent = array_pop( $parent_stack );

// HTML for menu item containing childrens (close)
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 ) . '</ul>';
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ) . '</li>';
}
elseif ( !empty( $children[$option['value']['id']] ) )
{
$tab = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 );

// HTML for menu item containing childrens (open)
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a>',
$tab, // %1$s = tabulation
$option['value']['link'], // %2$s = link (URL)
$option['value']['title'] // %3$s = title
);
$this->html[] = $tab . "\t" . '<ul class="submenu">';

array_push( $parent_stack, $option['value']['parent_id'] );
$parent = $option['value']['id'];
}
else
// HTML for menu item with no children (aka "leaf")
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a></li>',
str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ), // %1$s = tabulation
$option['value']['link'], // %2$s = link (URL)
$option['value']['title'] // %3$s = title
);
}

// HTML wrapper for the menu (close)
$this->html[] = '</ul>';

return implode( "\r\n", $this->html );
}
}

$menu = new MenuBuilder();
echo '<pre>' . $menu->get_menu_html() . '</pre>';



?>

It still has "each" in there, but it's isolated so it should be easier to convert over.
Can play with it here: https://sandbox.onlinephpfunctions.com/

Working on getting this converted now...

Here's a drop-in replacement I wrote:

    public function each(&$ar)
{
$key = key($ar);
if($key === null){return false;}
$current = current($ar);

try
{
return [$key,$current,'key'=>$key,'value'=>$current];
}finally{
next($ar);
};

}

Then instead of:

while ( $loop && ( ( $option = each( $children[$parent] ) ) || ( $parent > $root_id ) ) )

use:

while ( $loop && ( ( $option = $this->each( $children[$parent] ) ) || ( $parent > $root_id ) ) )

i.e. using $this->each instead of each.

Final code:

<?php

/**
* Generate HTML for multi-dimensional menu from MySQL database
* with ONE QUERY and WITHOUT RECURSION
* @author J. Bruni
*/
class MenuBuilder
{

/**
* Menu items
*/
var $items = array();

/**
* HTML contents
*/
var $html = array();


public function each(&$ar)
{
$key = key($ar);
if($key === null){return false;}
$current = current($ar);

try
{
return [$key,$current,'key'=>$key,'value'=>$current];
}finally{
next($ar);
};

}


/**
* Get all menu items from database
*/
function get_menu_items()
{
// Change the field names and the table name in the query below to match tour needs
return [
['id'=>1, 'parent_id'=>0, 'title'=>'title 1','link'=>'link 1','position'=>'0'],
['id'=>2, 'parent_id'=>1, 'title'=>'title 2','link'=>'link 2','position'=>'0'],
['id'=>3, 'parent_id'=>1, 'title'=>'title 3','link'=>'link 3','position'=>'0'],
['id'=>4, 'parent_id'=>0, 'title'=>'title 4','link'=>'link 4','position'=>'0'],
];
}

/**
* Build the HTML for the menu
*/
function get_menu_html( $root_id = 0 )
{
$this->html = array();
$this->items = $this->get_menu_items();

foreach ( $this->items as $item )
$children[$item['parent_id']][] = $item;

// loop will be false if the root has no children (i.e., an empty menu!)
$loop = !empty( $children[$root_id] );

// initializing $parent as the root
$parent = $root_id;
$parent_stack = array();

// HTML wrapper for the menu (open)
$this->html[] = '<ul>';

while ( $loop && ( ( $option = $this->each( $children[$parent] ) ) || ( $parent > $root_id ) ) )
{
if ( $option === false )
{
$parent = array_pop( $parent_stack );

// HTML for menu item containing childrens (close)
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 ) . '</ul>';
$this->html[] = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ) . '</li>';
}
elseif ( !empty( $children[$option['value']['id']] ) )
{
$tab = str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 );

// HTML for menu item containing childrens (open)
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a>',
$tab, // %1$s = tabulation
$option['value']['link'], // %2$s = link (URL)
$option['value']['title'] // %3$s = title
);
$this->html[] = $tab . "\t" . '<ul class="submenu">';

array_push( $parent_stack, $option['value']['parent_id'] );
$parent = $option['value']['id'];
}
else
// HTML for menu item with no children (aka "leaf")
$this->html[] = sprintf(
'%1$s<li><a href="%2$s">%3$s</a></li>',
str_repeat( "\t", ( count( $parent_stack ) + 1 ) * 2 - 1 ), // %1$s = tabulation
$option['value']['link'], // %2$s = link (URL)
$option['value']['title'] // %3$s = title
);
}

// HTML wrapper for the menu (close)
$this->html[] = '</ul>';

return implode( "\r\n", $this->html );
}
}

$menu = new MenuBuilder();
echo '<pre>' . $menu->get_menu_html() . '</pre>';



?>

Tests fine over here:
https://sandbox.onlinephpfunctions.com/

The each() function is deprecated

The list($Formularfeld, $Wert)=each($_POST) is an outdated structure and should not be used anymore - I can only assume you found a really old tutorial somewhere.

The correct approach would be to preprocess the $_POST global and create a proper array with it, then iterate through it using foreach

foreach($_POST as $formularfeld => $wert) {
$mailinfo[$formularfeld] = $value; //Do NOT forget validation here, huge security problem
}

This way, we have a nice array called $mailinfo we can use later on, like this:

foreach($mailinfo as $formularfeld => $wert) {
if($formularfeld != "Send") {
$Mailnachricht .= $formularfeld.": ".$wert."\n";
}
}

The each() function is deprecated; can't figure out how to change to foreach

Change while (list ($item, $value) = each ($_FILES)){

to

foreach( $_FILES as $key => $file ) { }

the syntax above is really old and shouldn't be used.

Moreover you don't get extension properly in order to get extension use

$ext = pathinfo($file['name'], PATHINFO_EXTENSION);

php 7.2 each() function is deprecated

        while( list( $key ) = each( $u ) ) {
$u = $u[$key];
break;
}

There's absolutely no reason to do a loop here. You're just getting the first value out of the array and overwriting the array. The above loop can be rewritten in one line using current() which will pull the current value (first value if the array's pointer hasn't been altered) out of the array:

$u = current($u);

PHP 7.2: each is deprecated. How to convert these examples?

I realize you are looking for a universal equivalent drop-in replacement for those 2 examples that will be PHP 7.2 compatible and I hope someone here will answer this (as this may help many people moving to php 7.2 and higher), but I do have the answer specific to your script example, which will at least help you in this specific case if not universally.

Full disclosure: I know and work with that specific script (on a PHP 7.2 server).

while (($ut = each($user_tracking)) && ($listed++ < CONFIG_USER_TRACKING_SESSION_LIMIT)) {

Should be changed to:

foreach ($user_tracking as $ut['value']) {
if ($listed++ >= CONFIG_USER_TRACKING_SESSION_LIMIT) {
break;
}

Find:

while (($pu = each($ut['value']['last_page_url']))&&($du = each($ut['value']['page_desc']))) {

And change to:

foreach ($ut['last_page_url'] as $key => $pu) {
$du = $ut['page_desc'][$key];

This does require a small code rewrite below, as we have changed the arrays to strings, but still get the data we need.

Find:

<tr bgcolor=ffffff> 
<td class="dataTableContent" valign=top align="right"><?php echo date('H:i:s', $pu['key']); ?></td>
<td class="dataTableContent" nowrap valign=top align="left"> <a href="<?php echo $pu['value']; ?>" target="_new"><?php if ($du['value']!=''){ echo $du['value'];} ?></a> </td>
<td class="dataTableContent" width=100% align="left"><a href="<?php echo $pu['value']; ?>" target="_new"><?php echo chunk_split($pu['value'],40,"<br>"); ?></a></td>
</tr>

And change to:

<tr bgcolor=ffffff> 
<td class="dataTableContent" valign=top align="right"><?php echo date('H:i:s', $key); ?></td>
<td class="dataTableContent" nowrap valign=top align="left"> <a href="<?php echo $pu; ?>" target="_new"><?php if ($du!=''){ echo $du;} ?></a> </td>
<td class="dataTableContent" width=100% align="left"><a href="<?php echo $pu; ?>" target="_new"><?php echo chunk_split($pu,40,"<br>"); ?></a></td>
</tr>

Hope this helps.

Updating deprecated code, from each() to foreach()

It seems like the php team encourages you to manage array pointers yourself. you can replace the original array with an ArrayIterator wrapper.

$arrayItor = new ArrayIterator($array);

Then your code can be updated by using this iterator.

if ($n > 0){
if ($n !== $arrayItor->count()){
$ret = $arrayItor->current();
$arrayItor->next();
return (bool)$ret;
}
}

Another approach is current and next are not deprecated yet, so you can use them to replace the each function

if ($n > 0){
if ($n !== count($array)){
$ret = current($array);
next($array);
return (bool)$ret;
}
}

The each() function is deprecated. This message will be suppressed on further calls PHP 7.2

You should be able to swap out your each for a foreach in the most part.

<?php

foreach($this->images as $file => $info) {
// ...
}


Related Topics



Leave a reply



Submit