PHP/Instrukcja foreach

< PHP
Poprzedni rozdział: Instrukcja do while
Następny rozdział: Funkcje

Instrukcja foreach

edytuj

Ostatnią pętlą jest foreach. Ma ona specyficzne zastosowanie, ponieważ służy wyłącznie do przeglądania zawartości typów złożonych: tablic oraz obiektów. Kod wewnątrz niej jest powtarzany dla każdego z elementów tablicy, a on sam jest na ten czas przenoszony do tworzonej przez pętlę zmiennej. Wróćmy do naszego przykładu z pętlą for odczytującego zawartość pliku. Przepiszemy go z wykorzystaniem foreach:

<?php
$plik = file("plik.txt");
 	
echo '<ul>';
foreach($plik as $linia)
{
	echo '<li>'.trim($linia).'</li>';	
}
echo '</ul>';

Teraz skrypt ma o wiele bardziej przejrzystą budowę. Przyjrzyjmy się deklaracji pętli:

foreach($plik as $linia)

Mówi nam ona, że pętla ma analizować tablicę $plik, a aktualnie przetwarzany element ma być zapisany w zmiennej $linia.

Foreach umożliwia nam także zwracanie nazw indeksów elementów:

<?php
$plik = file('plik.txt');
 	
echo '<ul>';
foreach($plik as $numer => $linia)
{
	echo '<li>Linia #'.$numer.': '.trim($linia).'</li>';	
}
echo '</ul>';

Foreach ma tę przewagę nad innymi pętlami, że wie, jakie elementy należą do tablicy i zawsze przetworzy tylko je. Gdybyśmy przed wyświetleniem pliku usunęli z niego np. linijkę 1, pętla for nie dałaby rady, próbując przetworzyć nieistniejący element. Nie robi oczywiście tego dla złośliwości, lecz dlatego, że operuje na liczniku i nie wie, do czego jest on przez nas dalej wykorzystywany.

<?php
$plik = file('plik.txt');
unset($plik[1]); // usuwamy linijkę o indeksie 1
echo '<ul>';
foreach($plik as $numer => $linia)
{
	echo '<li>Linia #'.$numer.': '.trim($linia).'</li>';	
}
echo '</ul>';

Tworzone przez foreach zmienne są jedynie kopiami oryginalnych wartości, dlatego próba ich modyfikacji wewnątrz pętli w żaden sposób nie wpłynie na zawartość tablicy:

<?php
$plik = file('plik.txt');
 
foreach($plik as $linia)
{
	$linia = 'Próba skasowania';
}
  	
echo '<pre>';
var_dump($plik);
echo '</pre>';

Wewnątrz pętli próbujemy przypisać wartość do zmiennej $linia. Owszem, udaje nam się to, ale nowa treść nie trafia w ogóle do tablicy i systemowe wyświetlenie jej zawartości ukazuje brak jakiejkolwiek reakcji. Czy zatem możliwe jest dokonywanie przypisań wewnątrz foreach? Oczywiście. Są dwie sztuczki. Pierwsza polega na wykorzystaniu zwracanego przez pętlę indeksu. Pousuwajmy z tablicy zbędne białe znaki:

<?php
$plik = file('plik.txt');
 
foreach($plik as $i => $linia)
{
	// jeszcze jakiś napis sobie doklejmy
	$plik[$i] = trim($linia).' [OK]';
}
  	
echo '<pre>';
var_dump($plik);
echo '</pre>';

Rozwiązanie to jest nieco trikowe, ale działa. Możemy jednak zastosować coś innego. PHP posiada pewien element zwany referencją. Ogólnie rzecz biorąc jest to odnośnik do zmiennej, który zachowuje się tak, jak ona. Modyfikacja referencji powoduje także modyfikację oryginalnego elementu. Począwszy od PHP 5, referencje można używać w pętli foreach. Wystarczy poprzedzić w jej deklaracji zmienną $linia znakiem &:

<?php
$plik = file('plik.txt');
 
foreach($plik as &$linia)
{
	$linia = trim($linia).' [OK]';
}
  	
echo '<pre>';
var_dump($plik);
echo '</pre>';

Teraz modyfikacja zmiennej $linia jest równoznaczna z modyfikacją aktualnego elementu w tablicy $plik, ponieważ zmienna jest takim właśnie odnośnikiem. O referencjach szerzej powiemy w rozdziale Inne elementy składni.