Pętla foreach w PHP jest jednym z najwygodniejszych sposobów przeglądania elementów tablicy. Zamiast samodzielnie pilnować indeksu, zwiększać licznik i sprawdzać liczbę elementów, możemy kolejno pobierać wartości zapisane w tablicy. Konstrukcja foreach pozwala również odczytywać klucze tablic asocjacyjnych, modyfikować elementy przez referencję, przeglądać tablice wielowymiarowe oraz iterować po obiektach.
W praktycznych aplikacjach PHP foreach pojawia się bardzo często: podczas wyświetlania produktów, użytkowników, wyników zapytania, danych konfiguracyjnych, kategorii, pozycji zamówienia czy elementów pobranych z API. Warto więc poznać nie tylko podstawową składnię, ale również kilka zachowań, które potrafią prowadzić do trudnych do zauważenia błędów.
Co to jest foreach w PHP?
foreach jest konstrukcją języka PHP przeznaczoną przede wszystkim do przechodzenia kolejno przez elementy tablic i obiektów. Przy każdej iteracji PHP pobiera następny element i przypisuje jego wartość do wskazanej zmiennej.
Załóżmy, że mamy tablicę zawierającą nazwy języków programowania:
$languages = ['PHP', 'JavaScript', 'Python', 'Java'];
Możemy pobierać jej elementy pojedynczo:
foreach ($languages as $language) {
echo $language;
}
Pętla zostanie wykonana cztery razy. Przy pierwszym przejściu zmienna $language będzie zawierała PHP, przy drugim JavaScript, przy trzecim Python, a przy czwartym Java.
Nie musimy sprawdzać liczby elementów tablicy ani samodzielnie zwiększać indeksu. To PHP steruje przechodzeniem do kolejnych wartości.
Składnia pętli foreach
Najprostsza postać foreach wygląda następująco:
foreach ($tablica as $wartosc) {
// instrukcje
}
Zmienna znajdująca się przed słowem as wskazuje tablicę, którą chcemy przejrzeć. Druga zmienna przechowuje aktualnie przetwarzany element.
Możemy również pobrać klucz elementu:
foreach ($tablica as $klucz => $wartosc) {
// instrukcje
}
W takiej konstrukcji mamy dostęp jednocześnie do klucza oraz przypisanej do niego wartości.
Najprostszy przykład foreach
Weźmy prostą tablicę zawierającą imiona:
$names = ['Anna', 'Robert', 'Tomasz', 'Monika'];
foreach ($names as $name) {
echo $name . '
';
}
Wynikiem będzie:
Anna Robert Tomasz Monika
Za każdym razem zmienna $name otrzymuje wartość kolejnego elementu tablicy.
Nazwa zmiennej jest dowolna. Można więc napisać:
foreach ($names as $item) {
echo $item;
}
Technicznie będzie działało dokładnie tak samo. W praktyce warto jednak stosować nazwy opisujące zawartość zmiennej. Jeżeli tablica zawiera użytkowników, naturalnym wyborem będzie $user, a jeżeli produkty - $product.
foreach z kluczem i wartością
Każdy element tablicy PHP ma klucz. W zwykłej tablicy indeksowanej są to zazwyczaj kolejne liczby zaczynające się od zera.
$colors = ['czerwony', 'zielony', 'niebieski'];
foreach ($colors as $key => $color) {
echo $key . ': ' . $color . '
';
}
Otrzymamy:
0: czerwony 1: zielony 2: niebieski
Pierwsza zmienna po as i przed operatorem => przechowuje klucz, a druga wartość elementu.
Ta forma jest szczególnie przydatna przy tablicach asocjacyjnych.
foreach i tablica asocjacyjna
W tablicy asocjacyjnej zamiast kolejnych indeksów liczbowych możemy stosować własne klucze.
$user = [
'name' => 'Anna',
'city' => 'Warszawa',
'age' => 32
];
Do przejrzenia wszystkich danych możemy zastosować:
foreach ($user as $key => $value) {
echo $key . ': ' . $value . '
';
}
Wynik:
name: Anna city: Warszawa age: 32
W pierwszym przebiegu zmienna $key zawiera name, a $value zawiera Anna. Następnie otrzymujemy city oraz Warszawa, a na końcu age oraz 32.
Taki sposób iterowania często pojawia się przy konfiguracji aplikacji, danych przekazanych z formularzy czy strukturach odczytanych z plików JSON.
Indeksy tablicy w foreach
Nie należy zakładać, że klucze liczbowe zawsze będą kolejnymi liczbami 0, 1, 2, 3. Tablica może mieć dowolne indeksy.
$products = [
10 => 'Monitor',
25 => 'Klawiatura',
80 => 'Mysz'
];
foreach ($products as $id => $product) {
echo $id . ' - ' . $product . '
';
}
Otrzymamy:
10 - Monitor 25 - Klawiatura 80 - Mysz
To ważna różnica między foreach a pętlą opartą na liczniku. foreach nie wymaga, aby klucze tworzyły ciąg kolejnych liczb.
foreach podczas generowania HTML
Jednym z najczęstszych zastosowań foreach jest tworzenie fragmentów HTML na podstawie danych zapisanych w tablicy.
Załóżmy, że chcemy wygenerować listę kategorii:
$categories = ['PHP', 'JavaScript', 'Bazy danych', 'Linux']; echo '
- ';
foreach ($categories as $category) {
echo '
- ' . $category . ' '; } echo '
Po wykonaniu PHP przeglądarka otrzyma kod odpowiadający liście:
- PHP
- JavaScript
- Bazy danych
- Linux
W podobny sposób można generować tabele, karty produktów, pozycje menu czy wyniki wyszukiwania.
Zagnieżdżone pętle foreach
foreach może znajdować się wewnątrz innej pętli foreach. Jest to potrzebne między innymi wtedy, gdy tablica zawiera kolejne tablice.
$teams = [
'Frontend' => ['Anna', 'Tomasz'],
'Backend' => ['Robert', 'Marek']
];
foreach ($teams as $team => $members) {
echo $team . ':
';
foreach ($members as $member) {
echo '- ' . $member . '
';
}
}
Pierwsza pętla pobiera nazwę zespołu i tablicę jego członków. Druga przechodzi przez poszczególne osoby.
Efekt będzie podobny do:
Frontend: - Anna - Tomasz Backend: - Robert - Marek
Zagnieżdżanie pętli jest poprawne, ale w bardzo rozbudowanych strukturach może utrudniać czytanie kodu. Jeżeli pojawiają się trzy lub cztery poziomy zagnieżdżenia, często warto zastanowić się nad wydzieleniem części logiki do osobnej funkcji.
foreach i tablice wielowymiarowe
Typowym przypadkiem jest tablica zawierająca rekordy, na przykład dane produktów:
$products = [
[
'name' => 'Monitor',
'price' => 899
],
[
'name' => 'Klawiatura',
'price' => 249
],
[
'name' => 'Mysz',
'price' => 129
]
];
Możemy przejrzeć ją w następujący sposób:
foreach ($products as $product) {
echo $product['name'];
echo ' - ';
echo $product['price'] . ' zł';
echo '
';
}
Rezultat:
Monitor - 899 zł Klawiatura - 249 zł Mysz - 129 zł
W każdej iteracji zmienna $product jest osobną tablicą zawierającą dane jednego produktu.
Modyfikowanie wartości przez referencję
Domyślnie przypisanie wartości do zmiennej używanej przez foreach nie służy do bezpośredniej zmiany elementu znajdującego się w pierwotnej tablicy.
Jeżeli chcemy modyfikować elementy tablicy podczas iteracji, możemy użyć referencji oznaczonej symbolem &.
$prices = [100, 200, 300];
foreach ($prices as &$price) {
$price = $price * 1.10;
}
unset($price);
Po wykonaniu pętli tablica będzie zawierała wartości odpowiadające zwiększeniu cen o 10 procent.
110 220 330
Bardzo ważne jest tutaj:
unset($price);
Po zakończeniu pętli zmienna $price nadal może pozostawać referencją do ostatniego elementu tablicy. Jeżeli później użyjemy tej samej zmiennej, możemy nieświadomie zmodyfikować ostatni element.
Dlatego po pętli wykorzystującej:
foreach ($array as &$value)
dobrą praktyką jest zerwanie referencji:
unset($value);
Dlaczego referencja może powodować problem?
Rozważmy:
$numbers = [10, 20, 30];
foreach ($numbers as &$number) {
$number *= 2;
}
foreach ($numbers as $number) {
echo $number . '
';
}
Taki kod może prowadzić do zaskakujących rezultatów, ponieważ $number po pierwszej pętli nadal jest powiązane z ostatnim elementem tablicy. Bezpieczniejsza wersja to:
$numbers = [10, 20, 30];
foreach ($numbers as &$number) {
$number *= 2;
}
unset($number);
foreach ($numbers as $number) {
echo $number . '
';
}
To jeden z najważniejszych szczegółów związanych z foreach, o którym łatwo zapomnieć.
foreach i break
Instrukcja break pozwala natychmiast przerwać wykonywanie pętli.
$numbers = [3, 8, 12, 20, 25];
foreach ($numbers as $number) {
if ($number === 12) {
break;
}
echo $number . '
';
}
Wynik:
3 8
Gdy PHP natrafi na wartość 12, instrukcja break kończy całą pętlę. Elementy 20 i 25 nie zostaną już przetworzone.
Takie rozwiązanie jest przydatne na przykład podczas wyszukiwania pierwszego elementu spełniającego określony warunek.
foreach i continue
Instrukcja continue nie kończy całej pętli. Powoduje jedynie pominięcie pozostałych instrukcji w aktualnej iteracji i przejście do następnego elementu.
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as $number) {
if ($number === 3) {
continue;
}
echo $number . '
';
}
Wynik:
1 2 4 5
Wartość 3 została pominięta, ale pętla działa dalej.
Warunki wewnątrz foreach
W praktycznych programach bardzo często łączy się foreach z instrukcją if.
Załóżmy, że chcemy wyświetlić tylko ceny większe niż 100 zł:
$prices = [49, 120, 80, 299, 150];
foreach ($prices as $price) {
if ($price > 100) {
echo $price . ' zł
';
}
}
Wynik:
120 zł 299 zł 150 zł
Można również odwrócić warunek i wykorzystać continue:
foreach ($prices as $price) {
if ($price <= 100) {
continue;
}
echo $price . ' zł
';
}
Obie wersje prowadzą do tego samego wyniku. Druga konstrukcja może być wygodna wtedy, gdy po warunku znajduje się więcej instrukcji.
foreach i obiekty
foreach nie jest ograniczony wyłącznie do klasycznych tablic. PHP pozwala również iterować po obiektach. Zachowanie zależy jednak od rodzaju obiektu i widoczności jego właściwości.
Prosty przykład:
class User
{
public string $name = 'Anna';
public string $city = 'Kraków';
public int $age = 28;
}
$user = new User();
foreach ($user as $property => $value) {
echo $property . ': ' . $value . '
';
}
Wynikiem będzie:
name: Anna city: Kraków age: 28
W takim prostym przypadku foreach przechodzi po dostępnych publicznych właściwościach obiektu.
Bardziej zaawansowane klasy mogą implementować mechanizmy pozwalające dokładnie określić, w jaki sposób obiekt ma być iterowany. Stosowane są do tego między innymi interfejsy związane z Iterator i IteratorAggregate.
Alternatywna składnia foreach
PHP udostępnia także alternatywną składnię wykorzystującą dwukropek i endforeach.
foreach ($products as $product):
echo $product;
endforeach;
Działa ona tak samo jak zapis z nawiasami klamrowymi:
foreach ($products as $product) {
echo $product;
}
Alternatywna składnia bywa wygodna w szablonach HTML, ponieważ łatwiej zauważyć, gdzie kończy się dłuższy fragment odpowiadający pętli.
Przykładowa konstrukcja szablonowa może wyglądać następująco:
-
foreach ($products as $product):
// tutaj generowany jest element listy
endforeach;
W rzeczywistym pliku PHP kod PHP i HTML mogą być oczywiście przeplatane, ale w przykładach w tym artykule pomijamy znaczniki otwierające PHP, aby sam kod był czytelniejszy.
foreach czy for?
Tablice można przeglądać zarówno przy użyciu foreach, jak i klasycznej pętli for. Nie są to jednak konstrukcje identyczne.
Przykład z for:
$colors = ['red', 'green', 'blue'];
for ($i = 0; $i < count($colors); $i++) {
echo $colors[$i] . '
';
}
Ten sam efekt z foreach:
$colors = ['red', 'green', 'blue'];
foreach ($colors as $color) {
echo $color . '
';
}
| Cecha | foreach | for |
|---|---|---|
| Przeglądanie całej tablicy | Bardzo wygodne | Wymaga licznika |
| Tablice asocjacyjne | Naturalne zastosowanie | Mniej wygodne |
| Dostęp do numeru iteracji | Przez klucz lub dodatkowy licznik | Bezpośrednio przez zmienną sterującą |
| Dowolna zmiana licznika | Nie jest głównym zastosowaniem | Tak |
| Czytelność przy zwykłej iteracji | Zazwyczaj większa | Zależy od zastosowania |
Jeżeli zadaniem jest po prostu przejście przez wszystkie elementy tablicy, foreach jest najczęściej bardziej naturalnym wyborem. for lepiej sprawdza się wtedy, gdy potrzebujemy dokładnej kontroli nad licznikiem i sposobem jego zmiany.
Najczęstsze błędy przy foreach
1. Próba użycia foreach na niewłaściwej wartości
Jeżeli zmienna powinna zawierać tablicę, ale w określonej sytuacji zawiera inną wartość, kod może nie działać zgodnie z oczekiwaniami.
Przed iteracją warto więc wiedzieć, jaki typ danych otrzymujemy.
if (is_array($items)) {
foreach ($items as $item) {
echo $item;
}
}
2. Pomylenie klucza z wartością
W konstrukcji:
foreach ($users as $id => $user)
$id przechowuje klucz, a $user wartość. Przy dużej liczbie podobnie nazwanych zmiennych łatwo je pomylić, dlatego warto stosować czytelne nazewnictwo.
3. Pozostawienie referencji po zakończeniu foreach
Jeżeli zastosowano:
foreach ($items as &$item)
po zakończeniu pętli warto wykonać:
unset($item);
Pozostawiona referencja może prowadzić do nieoczekiwanej zmiany ostatniego elementu tablicy.
4. Niepotrzebne zagnieżdżanie wielu pętli
Dwie zagnieżdżone pętle są czymś zupełnie normalnym. Jeżeli jednak wewnątrz jednej pętli pojawia się kolejna, później następna, a każda zawiera dodatkowe instrukcje warunkowe, kod szybko staje się trudny do zrozumienia.
W takiej sytuacji warto część operacji przenieść do funkcji lub metody.
5. Założenie, że pierwszy klucz zawsze wynosi zero
Tablica PHP może mieć dowolne klucze:
$items = [
5 => 'A',
20 => 'B',
100 => 'C'
];
foreach poradzi sobie z taką tablicą bez problemu. Nie należy jednak zakładać, że klucze będą kolejno wynosiły 0, 1 i 2.
Praktyczny przykład - lista produktów
Połączmy kilka poznanych elementów w bardziej realistycznym przykładzie.
Mamy tablicę produktów:
$products = [
[
'name' => 'Monitor 27 cali',
'price' => 1299,
'available' => true
],
[
'name' => 'Klawiatura mechaniczna',
'price' => 349,
'available' => false
],
[
'name' => 'Mysz bezprzewodowa',
'price' => 189,
'available' => true
]
];
Chcemy wyświetlić tylko dostępne produkty:
foreach ($products as $product) {
if (!$product['available']) {
continue;
}
echo $product['name'];
echo ' - ';
echo $product['price'] . ' zł';
echo '
';
}
Wynik:
Monitor 27 cali - 1299 zł Mysz bezprzewodowa - 189 zł
Produkt niedostępny został pominięty dzięki instrukcji continue.
Możemy również wygenerować HTML:
echo '
- ';
foreach ($products as $product) {
if (!$product['available']) {
continue;
}
echo '
- '; echo $product['name']; echo ' - '; echo $product['price'] . ' zł'; echo ' '; } echo '
Ten prosty schemat odpowiada temu, co dzieje się w znacznie większych aplikacjach. Dane mogą pochodzić z bazy danych, API albo innego źródła, a foreach przegląda kolejne rekordy i pozwala wykonać dla każdego z nich odpowiednie operacje.
FAQ - foreach w PHP
foreach służy przede wszystkim do kolejnego przeglądania elementów tablic i obiektów. Przy każdej iteracji aktualny element jest przypisywany do wskazanej zmiennej, dzięki czemu nie trzeba samodzielnie zarządzać licznikiem pętli.
Podstawowa składnia to foreach ($array as $value). Jeżeli potrzebny jest również klucz elementu, można użyć konstrukcji foreach ($array as $key => $value).
Klucz pobieramy przez konstrukcję $key => $value. Przykładowo foreach ($users as $id => $user) przypisuje klucz elementu do zmiennej $id, a jego wartość do $user.
Tak. Jeżeli wartość w pętli zostanie pobrana przez referencję, na przykład foreach ($items as &$item), można bezpośrednio modyfikować elementy oryginalnej tablicy. Po zakończeniu takiej pętli warto wykonać unset($item), aby zerwać pozostającą referencję.
Do natychmiastowego zakończenia pętli służy instrukcja break. Po jej wykonaniu PHP przechodzi do kodu znajdującego się po pętli.
Do pominięcia aktualnej iteracji służy continue. PHP przestaje wykonywać dalszą część bieżącego przebiegu pętli i przechodzi do następnego elementu.
Tak. Jedna pętla foreach może znajdować się wewnątrz drugiej. Jest to często stosowane podczas przeglądania tablic wielowymiarowych, na przykład list zespołów i przypisanych do nich użytkowników.
Do zwykłego przechodzenia przez wszystkie elementy tablicy najczęściej wygodniejszy i czytelniejszy jest foreach. Pętla for jest przydatna wtedy, gdy potrzebna jest pełna kontrola nad licznikiem, jego wartością początkową, końcową i sposobem zmiany.
Tak. foreach bardzo dobrze nadaje się do tablic asocjacyjnych. Konstrukcja foreach ($array as $key => $value) pozwala jednocześnie pobierać nazwę klucza i przypisaną do niego wartość.
Tak. PHP pozwala używać foreach również z obiektami. W prostych przypadkach można przechodzić po dostępnych właściwościach publicznych, a bardziej zaawansowane klasy mogą definiować własny sposób iteracji.
PHP foreach - podsumowanie
foreach jest jedną z podstawowych konstrukcji, które warto dobrze opanować podczas nauki PHP. Pozwala w prosty sposób przechodzić przez tablice bez ręcznego zarządzania indeksem, a jednocześnie daje dostęp zarówno do wartości, jak i kluczy poszczególnych elementów.
Najczęściej wystarcza prosty zapis foreach ($array as $value). W przypadku tablic asocjacyjnych bardzo przydatna jest wersja foreach ($array as $key => $value). Możemy też łączyć pętlę z instrukcjami if, break i continue, przeglądać tablice wielowymiarowe i modyfikować elementy przez referencję.
Szczególną uwagę warto zwrócić właśnie na referencje. Konstrukcja foreach ($array as &$value) pozwala zmieniać oryginalną tablicę, ale po zakończeniu pętli dobrze jest zastosować unset($value). Jest to niewielki szczegół składni, który może uchronić przed bardzo trudnym do zauważenia błędem.
W typowej aplikacji PHP foreach znajdziemy w wielu miejscach - od prostego wyświetlania listy po przetwarzanie wyników z bazy danych, danych API, konfiguracji i złożonych struktur obiektowych. Dlatego nie jest to jedynie pętla dla początkujących, ale jedno z podstawowych narzędzi używanych także w rzeczywistych projektach.

Komentarze