¿Cómo determinar la primera y la última iteración en un bucle foreach?

La pregunta es sencilla. Tengo un bucle foreach en mi código:

foreach($array as $element) {
    //code
}

En este bucle, quiero reaccionar de manera diferente cuando estamos en la primera o última iteración.

¿Cómo hacer esto?

Solución

Podrías usar un contador:

$i = 0;
$len = count($array);
foreach ($array as $item) {
    if ($i == 0) {
        // first
    } else if ($i == $len - 1) {
        // last
    }
    // …
    $i++;
}
Comentarios (11)

Podrías eliminar el primer y el último elemento de la matriz y procesarlos por separado.
Así:

<?php
$array = something();
$first = array_shift($array);
$last = array_pop($array);

// do something with $first
foreach ($array as $item) {
 // do something with $item
}
// do something with $last
?>

Quitando todo el formato a CSS en lugar de etiquetas inline mejoraría tu código y aceleraría el tiempo de carga.

También podrías evitar mezclar el HTML con la lógica de php siempre que sea posible.
Tu página podría ser mucho más legible y mantenible separando las cosas así:

<?php
function create_menu($params) {
  //retirive menu items 
  //get collection 
  $collection = get('xxcollection') ;
  foreach($collection as $c) show_collection($c);
}

function show_subcat($val) {
  ?>
    <div class="sub_node" style="display:none">

      <a id="'.$val['xsubcatid'].'" href="javascript:void(0)" onclick="getProduct(this , event)" class="sub_node_links"  >
        <?php echo $val['xsubcatname']; ?>
      </a>
    </div>
  <?php
}

function show_cat($item) {
  ?>
    <div class="node" >


      <?php echo $item['xcatname']; ?>
      <?php 
        $subcat = get_where('xxsubcategory' , array('xcatid'=>$item['xcatid'])) ;
        foreach($subcat as $val) show_subcat($val);
      ?>
    </div>
  <?php
}

function show_collection($c) {
  ?>
    <div class="parent" style="direction:rtl">


      <?php echo $c['xcollectionname']; ?>
      <?php
        //get categories 
        $cat = get_where('xxcategory' , array('xcollectionid'=>$c['xcollectionid']));
        foreach($cat as $item) show_cat($item);
      ?>
    </div>
  <?php
}
?>
Comentarios (0)

1: ¿Por qué no utilizar una simple sentencia for? Asumiendo que estás usando un array real y no un Iterator podrías comprobar fácilmente si la variable contador es 0 o uno menos que el número entero de elementos. En mi opinión esta es la solución más limpia y comprensible...

$array = array( ... );

$count = count( $array );

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

    $current = $array[ $i ];

    if ( $i == 0 )
    {

        // process first element

    }

    if ( $i == $count - 1 )
    {

        // process last element

    }

}

2: Deberías considerar el uso de Conjuntos Anidados para almacenar tu estructura de árbol. Además puedes mejorar el conjunto utilizando funciones recursivas.

Comentarios (1)