Jak zbudować tablicę indeksowaną, asocjacyjną i wielowymiarową w PHP, jak przejść po niej pętlą foreach i które wbudowane funkcje tablicowe wracają w pytaniach: count, sort, in_array, implode i explode. Lekcja 12.4 kursu INF.03.
Tablica to zmienna, która trzyma wiele wartości pod jedną nazwą, każdą pod własnym kluczem: numerem albo napisem. Należy do typów złożonych, więc jedna nazwa $produkty wystarczy na całą listę towarów, zamiast trzech osobnych zmiennych na trzy ceny. W części pisemnej wracają pytania o wartość elementu o podanym indeksie, o to, co wypisze count, która definicja jest tablicą asocjacyjną, co pokaże print_r oraz w której tablicy czekają dane z formularza. W zadaniu praktycznym tablica jest wszędzie: wiersz pobrany z bazy to tablica asocjacyjna, a dane wysłane formularzem czekają w $_POST.
Tablica indeksowana
Tablica indeksowana to tablica, w której kluczami są kolejne liczby całkowite, liczone od zera. Tworzy się ją nawiasami kwadratowymi albo starszym zapisem array(). Oba zapisy działają tak samo i oba pojawiają się w arkuszach, więc trzeba rozpoznawać każdy z nich.
<?php
$ceny = [120, 45, 650];
$stare = array(120, 45, 650);
echo $ceny[0];
Pierwszy element ma indeks 0, więc ten kod wypisuje 120, $ceny[1] to 45, a $ceny[2] to 650. Element dokłada się na koniec pustymi nawiasami kwadratowymi, a wartość pod istniejącym indeksem zmienia się zwykłym przypisaniem. Liczbę elementów oddaje count (POLICZ), przy czym jest to liczba elementów, a nie największy indeks: ostatni element stoi pod indeksem count minus jeden.
<?php
$ceny = [120, 45, 650];
$ceny[] = 25;
$ceny[1] = 49;
echo $ceny[1] . " " . count($ceny) . " " . $ceny[count($ceny) - 1];
Po elementach przechodzi się pętlą. for (DLA) nadaje się tam, gdzie potrzebny jest sam numer elementu, bo licznik $i biegnie od zera do count minus jeden. foreach (DLA KAŻDEGO) sama bierze kolejne wartości i nie da się w niej pomylić granicy, więc do zwykłego przeglądania tablicy jest wygodniejsza; obie opisuje lekcja o instrukcjach sterujących. <?php
$ceny = [120, 45, 650];
for ($i = 0; $i < count($ceny); $i++) {
echo $i . ": " . $ceny[$i] . "<br>";
}
Wynik pokazuje obraz z okna przeglądarki. W źródle strony stoi jeden wiersz, a rozbija go na trzy dopiero znacznik <br> doklejany w pętli.
Pułapka: odczyt spoza zakresu, na przykład $ceny[3] z tablicy o trzech elementach, daje ostrzeżenie Warning: Undefined array key 3 i wartość null, a nie zero.
Tablica asocjacyjna
Tablica asocjacyjna (associative array, tablica z kluczami) to tablica, w której kluczem jest napis wybrany przez piszącego, a nie kolejny numer. Klucz oddziela się od wartości strzałką =>, a odczyt wygląda tak samo jak przy indeksie, tylko w nawiasie stoi napis w cudzysłowie. Taka tablica opisuje jedną rzecz z kilku pól: produkt ma nazwę, cenę i stan magazynowy.
<?php
$produkt = ['nazwa' => 'Mysz', 'cena' => 45, 'sztuk' => 0];
echo $produkt['cena'];
foreach ($produkt as $klucz => $wartosc) {
echo "<br>" . $klucz . " = " . $wartosc;
}
45
nazwa = Mysz
cena = 45
sztuk = 0
Wersja foreach z dwiema zmiennymi bierze osobno klucz i osobno wartość, więc jednym przejściem wypisuje całą zawartość. Przed odczytem klucza, którego może nie być, sprawdza się isset (CZY USTAWIONE): zwraca prawdę, gdy klucz istnieje i nie ma wartości null. Gdy trzeba odróżnić klucz z wartością null od klucza nieistniejącego, służy do tego array_key_exists. Same klucze oddaje array_keys, same wartości array_values, obie jako nową tablicę indeksowaną.
<?php
$dane = ['nazwa' => 'Mysz', 'cena' => 45];
if (isset($dane['cena'])) {
echo "cena jest<br>";
}
print_r(array_keys($dane));
cena jest
Array
(
[0] => nazwa
[1] => cena
)
Tablice asocjacyjne przychodzą do skryptu gotowe z dwóch stron. Wiersz pobrany z bazy funkcją mysqli_fetch_assoc ma klucze równe nazwom kolumn, więc cena z tabeli produkt czeka pod $wiersz['cena'], o czym mówi lekcja o PHP i bazie danych. Dane z formularza trafiają do tablic superglobalnych $_POST albo $_GET, gdzie kluczem jest atrybut name pola: pole o nazwie ilosc czeka pod $_POST['ilosc']. Opisuje to lekcja o formularzach w PHP. Tablica wielowymiarowa
Tablica wielowymiarowa to tablica, której elementami są kolejne tablice. Lista produktów sklepu wygląda wtedy jak tabelka: każdy wiersz to jedna tablica asocjacyjna z tymi samymi kluczami, a do pojedynczego pola trzeba podać dwa klucze, najpierw numer wiersza, potem nazwę kolumny.
Tablica indeksowana ma klucze 0, 1 i 2, asocjacyjna klucze nazwa, cena i sztuk, a w wielowymiarowej cena drugiego produktu wynosi 45
<?php
$produkty = [
['nazwa' => 'Klawiatura', 'cena' => 120, 'sztuk' => 15],
['nazwa' => 'Mysz', 'cena' => 45, 'sztuk' => 0],
['nazwa' => 'Monitor 24', 'cena' => 650, 'sztuk' => 4],
];
echo $produkty[1]['cena'] . " " . count($produkty);
Zapis $produkty[1]['cena'] czyta się od lewej: element o indeksie 1, czyli drugi wiersz, a w nim pole o kluczu cena. Wiersze są numerowane od zera, więc Klawiatura ma indeks 0, Mysz 1, a Monitor 24 indeks 2. count($produkty) liczy same wiersze, nie pola w nich. Takie dane wypisuje się na stronę dwiema pętlami: zewnętrzna bierze wiersz i otacza go znacznikami <tr>, wewnętrzna bierze kolejne pola wiersza i wkłada każde w <td>.
<?php
$produkty = [
['nazwa' => 'Mysz', 'cena' => 45],
['nazwa' => 'Monitor 24', 'cena' => 650],
];
echo "<table>";
foreach ($produkty as $wiersz) {
echo "<tr>";
foreach ($wiersz as $pole) {
echo "<td>" . $pole . "</td>";
}
echo "</tr>";
}
echo "</table>";
<table><tr><td>Mysz</td><td>45</td></tr><tr><td>Monitor 24</td><td>650</td></tr></table>
Dokładnie taki kształt ma pętla wypisująca wynik zapytania: zamiast tablicy wpisanej ręcznie stoi tam wiersz po wierszu pobierany z bazy, a reszta zostaje bez zmian.
Wbudowane funkcje tablicowe
Funkcja tablicowa to gotowa funkcja PHP, która liczy, szuka albo przestawia elementy tablicy, więc nie trzeba pisać do tego własnej pętli. W tabeli każdy przykład zaczyna od tej samej, świeżej tablicy $t = [3, 1, 2].
Funkcja
Co robi
Przykład
Wynik
count
liczy elementy
count($t)
3
sizeof
to samo co count, druga nazwa
sizeof($t)
3
array_push
dokłada element na koniec
array_push($t, 9)
3, 1, 2, 9
array_pop
zdejmuje ostatni element i oddaje jego wartość
array_pop($t)
2
array_shift
zdejmuje pierwszy element i przenumerowuje resztę
array_shift($t)
3
array_unshift
wstawia element na początek
array_unshift($t, 9)
9, 3, 1, 2
in_array
sprawdza, czy wartość jest w tablicy
in_array(1, $t)
true
array_search
oddaje klucz pierwszej takiej wartości
array_search(1, $t)
1
array_sum
sumuje wartości
array_sum($t)
6
max
największa wartość
max($t)
3
min
najmniejsza wartość
min($t)
1
sort
sortuje rosnąco i numeruje klucze od nowa
sort($t)
1, 2, 3
rsort
sortuje malejąco
rsort($t)
3, 2, 1
asort
sortuje po wartościach, zachowuje klucze
asort($t)
1, 2, 3 z kluczami 1, 2, 0
ksort
sortuje po kluczach
ksort($t)
3, 1, 2, bez zmiany
array_reverse
odwraca kolejność
array_reverse($t)
2, 1, 3
array_merge
łączy tablice w jedną
array_merge($t, [7])
3, 1, 2, 7
array_slice
wycina fragment od podanej pozycji
array_slice($t, 1, 2)
1, 2
implode
skleja elementy w jeden napis
implode(", ", $t)
3, 1, 2
explode
dzieli napis na tablicę
explode(";", "a;b;c")
a, b, c
array_map
wywołuje funkcję dla każdego elementu
array_map('abs', [-4, 9])
4, 9
Funkcje sortujące pracują na oryginale: sort($t) przestawia elementy w samej zmiennej i oddaje prawdę, a nie nową tablicę, więc zapis $t = sort($t) niszczy dane. Nazwy ksort i asort biorą się od tego, co jest kluczem porządku: k to klucz, a to asocjacja, czyli para klucz i wartość zostaje razem.
Pułapka: sort numeruje klucze od nowa, więc tablica asocjacyjna po nim traci swoje klucze i zostaje z indeksami 0, 1, 2. Klucze zachowuje asort, a według kluczy porządkuje ksort.
Wypisywanie tablicy do kontroli
Zwykły echo nie potrafi wypisać tablicy: pokazuje słowo Array i dokłada ostrzeżenie Warning: Array to string conversion. Do zajrzenia do środka służą dwie funkcje. print_r (WYPISZ CZYTELNIE) pokazuje klucze i wartości, var_dump (ZRZUT ZMIENNEJ) dokłada do nich typ i długość każdej wartości. Obie wypisują wynik w wielu wierszach, więc na stronie otacza się je znacznikiem <pre>, inaczej przeglądarka sklei wszystko w jedną linię.
<?php
$produkt = ['nazwa' => 'Mysz', 'cena' => 45];
echo "<pre>";
print_r($produkt);
var_dump($produkt['cena']);
echo "</pre>";
Array
(
[nazwa] => Mysz
[cena] => 45
)
int(45)
Przykłady z wynikiem
Trzy typowe rachunki na danych ze sklepu z działu o bazach danych: ceny to Klawiatura 120, Mysz 45 i Monitor 24 za 650. Pierwszy liczy sumę i średnią.
<?php
$ceny = [120, 45, 650];
$suma = array_sum($ceny);
$srednia = $suma / count($ceny);
echo "Suma: " . $suma . ", średnia: " . round($srednia, 2);
Suma: 815, średnia: 271.67
Drugi przechodzi po tablicy wielowymiarowej i wypisuje tylko produkty tańsze niż 100.
<?php
$produkty = [
['nazwa' => 'Klawiatura', 'cena' => 120],
['nazwa' => 'Mysz', 'cena' => 45],
['nazwa' => 'Kabel HDMI', 'cena' => 25],
];
foreach ($produkty as $p) {
if ($p['cena'] < 100) {
echo $p['nazwa'] . " " . $p['cena'] . " zl<br>";
}
}
Mysz 45 zl
Kabel HDMI 25 zl
Trzeci zamienia tablicę na napis i napis na tablicę, czyli robi to, co implode i explode robią w każdą stronę.
<?php
$nazwy = ['Klawiatura', 'Mysz', 'Monitor 24'];
echo implode(", ", $nazwy) . "<br>";
$litery = explode(";", "a;b;c");
echo count($litery) . " " . $litery[0];
Klawiatura, Mysz, Monitor 24
3 a
Na egzaminie
Pytania pisemne o tablice mają kilka stałych kształtów. Pierwszy to poprawna definicja: tablicą asocjacyjną jest array("a" => 1, "b" => 2), bo klucz od wartości oddziela strzałka =>, a odpowiedzi ze znakiem równości albo z samymi wartościami odpadają. Drugi to wartość elementu: w ramce stoi tablica i pytanie, co wypisze echo dla podanego indeksu. Trzeci to count, która oddaje liczbę elementów, a nie największy indeks. Czwarty to liczba powtórzeń echo w pętli foreach: instrukcja wykonuje się tyle razy, ile jest elementów, a nie raz dla całej tablicy. Piąty to wydruk print_r, w którym w nawiasach kwadratowych stoją klucze, a po strzałce wartości. Szósty to formularz: pole <input name="im"> po wysłaniu wartości Janek daje wpis w tablicy $_POST pod indeksem im, a nie odwrotnie. Siódmy to sortowanie: tablicę asocjacyjną według indeksów porządkuje ksort, według wartości asort. Ósmy to in_array, które mówi tylko, czy wartość jest w tablicy, podczas gdy array_search oddaje jej klucz. Dziewiąty to ostrzeżenie widoczne na stronie: Warning: Undefined array key znaczy próbę odwołania się do nieistniejącego elementu tablicy, najczęściej odczyt z $_POST przed wysłaniem formularza. Dziesiąty to nazwa pętli: operacje na wszystkich elementach tablicy z automatycznym indeksowaniem wykonuje foreach, a nie for, while ani do...while.
Pułapka: indeksy liczą się od zera, więc trzeci element ma indeks 2, a ostatni element tablicy, dla której count daje 4, stoi pod indeksem 3.
W zadaniu praktycznym tablice wchodzą w dwóch miejscach. Wiersz pobrany z bazy funkcją mysqli_fetch_assoc jest tablicą asocjacyjną z kluczami równymi nazwom kolumn, więc nazwę produktu wypisuje $wiersz['nazwa']. Ta sama funkcja w wersji mysqli_fetch_row oddaje tablicę indeksowaną, więc pierwsza kolumna z SELECT to $wiersz[0], druga $wiersz[1] i tak dalej, a mysqli_fetch_array daje oba komplety kluczy naraz. Pętla pobierająca kolejne wiersze wypisuje je potem według wzoru z arkusza, jako pozycje <li> albo wiersze <tr>. Drugie miejsce to formularz wysłany metodą POST do tej samej strony: wartość pola czyta się z $_POST i wstawia do klauzuli WHERE zapytania, a nazwa klucza musi zgadzać się co do znaku z atrybutem name w formularzu HTML. Ściąga
$t = [120, 45, 650];
tablica indeksowana, klucze 0, 1 i 2
$t = array(120, 45);
starszy zapis tablicy, działa tak samo
$t[] = 25;
dokłada element na koniec
$t[0]
pierwszy element tablicy
count($t) - 1
indeks ostatniego elementu
$p = ['cena' => 45];
tablica asocjacyjna, kluczem jest napis
$p['cena']
odczyt wartości po kluczu
foreach ($t as $w)
pętla po samych wartościach
foreach ($p as $k => $w)
pętla po kluczach i wartościach
isset($p['cena'])
czy klucz istnieje i nie jest null
$produkty[1]['cena']
pole drugiego wiersza tablicy wielowymiarowej
in_array(45, $t)
czy wartość jest w tablicy
array_search(45, $t)
klucz pierwszej takiej wartości
array_sum($t)
suma wartości
sort($t)
sortuje rosnąco, klucze od nowa
asort($p)
sortuje po wartościach, klucze zostają
ksort($p)
sortuje po kluczach
implode(", ", $t)
tablica na jeden napis
explode(";", $s)
napis na tablicę
print_r($t)
czytelny wydruk całej tablicy
$_POST['imie']
wartość pola formularza o name="imie"
$wiersz['nazwa']
kolumna wiersza z mysqli_fetch_assoc
Pobierz ściągę PDF