Poznamy dwa nowe typy danych, jakimi są tablice oraz tablice asocjacyjne. Nauczymy się je tworzyć, wyświetlać, korzystać z nich oraz dedykowanych im funkcjom w PHP, wykonamy też pierwsze ćwiczenia utrwalające zdobytą już wiedzę.

Do dzieła.

Tworzenie tablic – listy, tablice asocjacyjne

Stwórzmy sobie tablicę prostą, czyli listę jakichś elementów, której kluczami są indeksy (liczone od zera) a wartości są dowolne, mogą być typu tekstowego:

<?php 


$stack = array("orange", "banana", "apple", "raspberry");
print_r($stack);
//Array ( [0] => orange [1] => banana [2] => apple [3] => raspberry )
?> 

Funkcja print_r służy do wypisywania całych tablic. Klucze (którymi są indeksy) mamy tam wyświetlone w nawiasach kwadratowych [ ] zaś po strzałce mamy wartości.

Oczywiście nie musimy używać funkcji array(), możemy zastosować literał

<?php 


$stack = ["orange", "banana", "apple", "raspberry"];
print_r($stack);
//Array ( [0] => orange [1] => banana [2] => apple [3] => raspberry )
?> 

To już wedle naszych upodobań. Podobnie możemy tworzyć tablice asocjacyjne, czyli takie, w których istnieje klucz (przez nas zdefiniowany, zamiast indeksu) oraz wartość.

Poprzez array():

<?php 

$array = array(
    "foo" => "bar",
    "bar" => "foo",
);
print_r($array);
//Array ( [foo] => bar [bar] => foo )
?> 

Poprzez literał:

<?php 

$array = [
    "foo" => "bar",
    "bar" => "foo",
];
print_r($array);
//Array ( [foo] => bar [bar] => foo )

Używanie indeksów/kluczy

Poprzez indeks możemy uzyskać dostęp do elementów tablicy. Tablica-lista jest indeksowana od 0, czyli pierwszy element ma indeks 0, następne o 1 większy.

Oto wypisanie elementu pod indeksem zerowym:

<?php 

$stack = array("orange", "banana", "apple", "raspberry");
echo $stack[0];
//orange

Elementy możemy nie tylko wypisywać, ale także modyfikować, korzystając z indeksu.

Wypiszmy sobie element zerowy, następnie użyjmy na nim funkcji ucfirst (pierwsza litera zostanie zapisana wielką):

<?php 

$stack = array("orange", "banana", "apple", "raspberry");
echo $stack[0] . "</br>";
//orange
$stack[0] = ucfirst($stack[0]);
echo $stack[0];
//Orange

Tak to się robi. Pod indeksem 0 chcemy mieć to, co już tam mamy, ale wrzucone w wywołanie funkcji ucfirst, która sprawi, że tekst zostanie zapisany wielką literą.

Jak widać – modyfikacji dokonaliśmy.

Podobnie możemy używać tablic asocjacyjnych, tam po prostu zamiast indeksu podajemy klucz:

<?php 

$array = [
    "foo" => "bar",
    "bar" => "foo",
];
echo $array["foo"];
//bar

Przejście w pętli – foreach, for

Pętla foreach pozwala nam przejść po elementach danej tablicy i na przykład je wypisać. Wygląda ona tak:

<?php 

$stack = ["orange", "banana", "apple", "raspberry"];
foreach ($stack as $fruit) {
    echo "$fruit </br>";
}

Korzystając z tej pętli możemy przechodzić po elementach tablicy.

Oczywiście możemy też zastosować pętlę for (klasyczną).

<?php 

$stack = ["orange", "banana", "apple", "raspberry"];

for($idx = 0; $idx < count($stack); $idx++) {
    echo $stack[$idx] . "</br>";
}
// orange
// banana
// apple
// raspberry

Wiemy, że elementy są indeksowane od 0. Funkcja count zwraca nam ilość elementów w tablicy (tutaj 4).

Elementy mają zatem indeksy od 0 (pierwszy element) do 3 (ostatni element). Możemy zatem zrobić pętlę for od 0 tak długo, aż idx mniejsze niż długość tablicy i tak te elementy wypisywać.

Na tablicy asocjacyjnej możemy już użyć tylko pętli foreach, ponieważ ta tablica nie ma numerycznych indeksów tylko klucze:

<?php 

$person = [
    "name" => "John",
    "age" => 30
];
foreach ($person as $key => $value) {
    echo "$key => $value </br>";
}
// name => John
// age => 30

W ten sposób korzystamy z foreach na tablicach asocjacyjnych. Do zmiennej $key ląduje klucz, do zmiennej $value wartość pod tym kluczem się znajdująca.

Sprawdzanie typu – is_array, array_is_list

Możemy sprawdzić, czy dana zmienna jest czy nie jest tablicą używając funkcji is_array:

<?php 
$var1 = "Text";

if (is_array($var1)) {
    echo "var1 is array";
}
else {
    echo "var1 is not an array";
}
//var1 is not an array

Mamy tutaj podstawową konstrukcję if-else z warunkiem. Oczywiście var1 nie jest tablicą.

Teraz jednak, warunek będzie prawdziwy:

<?php 
$var1 = ["orange", "banana", "apple", "raspberry"];

if (is_array($var1)) {
    echo "var1 is array";
}
else {
    echo "var1 is not an array";
}
//var1 is array

Mamy też funkcję, która sprawdza, czy nasza zmienna jest listą, czyli tablicą z indeksami jako kluczami.

<?php
$var1 = ["orange", "banana", "apple", "raspberry"];

if (array_is_list($var1)) {
    echo "var1 is list";
}
else {
    echo "var1 is not a list";
}
//var1 is list

Ta funkcja jest dosyć nowa (od PHP 8.1) więc może nam nie działać, jeżeli mamy starszą wersję PHP (możemy sobie sprawdzić jak działa w kompilatorze online).

Dla tablicy asocjacyjnej, która nie ma kluczy-indeksów, ta funkcja zwróci fałsz:

<?php
$var1 = [
    "name" => "John",
    "age" => 30
];

if (array_is_list($var1)) {
    echo "var1 is list";
}
else {
    echo "var1 is not a list";
}
//var1 is not a list

Podstawowe funkcje – push, pop, in_array

Aby „zrzucić” ostatni element z tablicy, korzystamy z funkcji array_pop:

<?php 
$var1 = ["orange", "banana", "apple", "raspberry"];
$last = array_pop($var1);
print_r($var1);
//Array ( [0] => orange [1] => banana [2] => apple )

Funkcja array_pop usuwa ostatni element tablicy i zarazem go zwraca. Przypisaliśmy go sobie do zmiennej $last i on tam jest, co możemy sprawdzić, natomiast z tablicy $var1 został usunięty.

Dodawać elementy na końcu możemy na dwa sposoby:

<?php 
$arr = [1, 2, 3];
$arr[] = 4;
array_push($arr, 5);
print_r($arr);
//Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )

Czyli albo zapis z pustym nawiasem [], albo array_push, nazwa tablicy i element, który chcemy wepchnąć na koniec.

Dostajemy tablicę liczb od 1 do 5. Zobaczyć, czy te liczby tam są możemy przy pomocy funkcji in_array:

<?php 
$arr = [1, 2, 3];
$arr[] = 4;
array_push($arr, 5);
if(in_array(4, $arr)){
    echo "4 is in array</br>";
}
if(in_array(5, $arr)){
    echo "5 is in array</br>";
}
// 4 is in array
// 5 is in array

Jak widać zarówno 4 jak i 5 znajdują się w tablicy arr, bo je tam dodaliśmy.

Mamy też inne, mniej znane funkcje tablic. Oto niektóre:

<?php 
$arr = [1, 2, 3];
$arr[] = 4;
echo array_sum($arr) . "</br>";
echo array_product($arr) . "</br>";
// 10
// 24

Funkcje array_sum i array_product wywołujemy na tablicach zawierających dane liczbowe.

Array_sum zwraca sumę elementów (elementy dodane do siebie) zaś array_product to nic innego jak elementy wymnożone przez siebie.

Do odwrócenia listy służy funkcja array_reverse:

<?php 
$arr = [1, 2, 3];
$arr[] = 4;
$reversed = array_reverse($arr);
print_r($arr);
print_r($reversed);
// Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) 
// Array ( [0] => 4 [1] => 3 [2] => 2 [3] => 1 )

Warto zwrócić uwagę, że array_reverse nie odwraca oryginalnej tablicy tylko zwraca nową, odwróconą, którą możemy przypisać do jakiejś zmiennej, u nas $reversed.

W dokumentacji PHP znaleźć możemy pełny spis wszystkich funkcji, oraz ich opis i przykłady działania.

Zadanie – lista bez duplikatów

W ramach zadania napiszemy sobie funkcję, która bierze jakąś listę jako argument i zwraca inną listę, która zawiera wszystkie jej elementy, ale bez duplikatów.

<?php 
function remove_duplicates($arr){
    $output = array();
    foreach($arr as $element){
        if(!in_array($element, $output)){
            $output[] = $element;
        }
    }
    return $output;
}
$arr1 = [1,2,3,1,2];
$arr2 = remove_duplicates($arr1);
print_r($arr2);
//Array ( [0] => 1 [1] => 2 [2] => 3 )

Tworzymy funkcję, która przyjmuje tablicę jako argument. Tworzymy drugą tablicę output.

Przechodzimy przez każdy element z naszego argumentu $arr. Jeżeli ten element nie znajduje się jeszcze w output, to go dodajemy. Znak „!” to znak negacji, zatem !in_array oznacza „jeżeli element się w tablicy nie znajduje”.

Ten, który się znajduje, drugi raz dodany nie zostanie. Zwracamy output.

Tym sposobem pozbawiliśmy tablicę duplikatów. A raczej – zwróciliśmy jej kopię, pozbawioną powtarzających się wartości.

Zrobiliśmy to tylko dla ćwiczenia, bowiem w PHP i od tego mamy funkcję wbudowaną. Nazywa się array_unique:

<?php 

$arr1 = [1,2,3,1,2];
$arr2 = array_unique($arr1);
print_r($arr2);
//Array ( [0] => 1 [1] => 2 [2] => 3 )

Działa tak samo, jak ta nasza, natomiast pisząc ją sobie mogliśmy przećwiczyć pewne umiejętności już nabyte oraz nauczyć się czegoś (pisanie funkcji, negacja poprzez „!”).

Zadanie 2 – dodaj liczby z zakresu, jeśli ich tam nie ma

Mamy taką oto tablicę:

<?php 

$arr1 = [2,4,9];

Chcemy do niej dodać liczby od 1 do 10 włącznie. Ale uwaga – jeżeli liczba taka już się w tablicy znajduje, nie dodajemy jej.

Możemy użyć pętli for:

<?php 

$arr1 = [2,4,9];
for($num = 0; $num <= 10; $num++){
    if(in_array($num, $arr1))
    {
    continue;
    }
    $arr1[] = $num;
}
sort($arr1);
print_r($arr1);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 )

Pętla for przechodzi po liczbach od 0 do 10 włącznie. Jeżeli taka liczba już się w naszej tablicy znajduje, używamy słówka kluczowego 'continue’.

Słówko kluczowe continue oznacza 'pomiń ten obrót pętli’, 'kontynuuj pętlę bez wykonywania reszty kodu’.

Jeżeli taka liczba się w naszej zmiennej nie znajduje, dodajemy ją do naszej zmiennej.

Po wykonaniu pętli użyliśmy jeszcze nieznanej nam funkcji sort. Jak się łatwo domyślić – sortuje elementy w naszej tablicy od najmniejszego do największego (w pętli dodawaliśmy elementy na końcu tablicy).

Czy można wykonać to inaczej? Oczywiście. Po pierwsze, in_array można zamienić na jego negację, czyli sprawdzać czy coś się w tablicy nie znajduje. Po drugie, zapis z nawiasami [] zamienić na array_push.

<?php 

$arr1 = [2,4,9];
for($num = 0; $num <= 10; $num++){
    if(!in_array($num, $arr1))
    {
    array_push($arr1, $num);
    }
    
}
sort($arr1);
print_r($arr1);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 )

W pętli przechodzimy po liczbach od 0 do 10 włącznie, jeżeli taka liczba się w naszej tablicy nie znajduje, dodajemy ją na końcu (tym razem – poprzez array_push).

Na koniec sortujemy tablicę i wyświetlamy.

Dodam, że jeżeli nasz block if zawiera tylko jedną instrukcję, możemy pominąć nawiasy klamrowe:

<?php 

$arr1 = [2,4,9];
for($num = 0; $num <= 10; $num++){
    if(!in_array($num, $arr1))
         array_push($arr1, $num);
    
    
}
sort($arr1);
print_r($arr1);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 )

Tak samo możemy zrobić z naszym poprzednim przykładem:

<?php 

$arr1 = [2,4,9];
for($num = 0; $num <= 10; $num++){
    if(in_array($num, $arr1))
        continue;
    $arr1[] = $num;
}
sort($arr1);
print_r($arr1);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 )

Nawiasy klamrowe są potrzebne tylko wtedy, gdy nasz blok if zawiera więcej niż jedną instrukcję.

Zadanie 3 – w pętli while opustosz listę, wyświetlając każdy element

Mamy taką oto listę:

<?php 

$arr1 = ["orange", "banana", "apple", "raspberry"];

Używając pętli while, chcemy wypisać każdy element tej listy, jednocześnie usuwając go z niej. Chcemy to zrobić, najlepiej, w kolejności.

Jak się do tego zabrać?

<?php 

$arr1 = ["orange", "banana", "apple", "raspberry"];
while(count($arr1) > 0){
    echo array_pop($arr1) . "</br>";
}
print_r($arr1);
// raspberry
// apple
// banana
// orange
// Array ( )

Tutaj mamy pętlę while z warunkiem „tak długo, jak liczba elementów w tablicy arr1 jest większa od 0”.

W echo wrzucamy wywołanie array_pop, które usuwa ostatni element z tablicy arr1 a zarazem zwraca go, dzięki czemu echo może go wypisać.

I rzeczywiście, wypisało, tablicę opustoszyło. Tylko zrobiło to w kolejności odwrotnej, bowiem array_pop usuwa i zwraca ostatni element tablicy.

Jak temu zaradzić?

$arr1 = ["orange", "banana", "apple", "raspberry"];
$arr1_reversed = array_reverse($arr1);
while(count($arr1) > 0){
    array_pop($arr1);
    echo array_pop($arr1_reversed) . "</br>";
}
print_r($arr1);
// orange
// banana
// apple
// raspberry
// Array ( )

Tutaj tworzymy kopię arr1, która jest odwrócona. Warunek dla pętli while nadal ten sam.

W każdym obrocie pętli zrzucamy z arr1 ostatni element przez array_pop. Zrzucamy ostatni element także z jej odwróconej wersji i to jego pokazujemy w echo.

Na koniec zarówno arr1 jak i arr1_reversed są puste, natomiast my wyświetliliśmy elementy w takiej kolejności, jak chcieliśmy.

Dla chcącego nic trudnego.

Zadanie 4 – stwórz listę liczb w zakresie razy 2

Chcemy stworzyć listę liczb w danym zakresie, ale pomnożonych przez 2.

$arr = array();
foreach(range(1,10) as $num)
    $arr[] = $num * 2;

print_r($arr);
// Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 [5] => 12 [6] => 14 [7] => 16 [8] => 18 [9] => 20 )

Tworzymy pustą zmienną. W pętli foreach przechodzimy po liczbach z zakresu od 1 do 10 (włącznie).

Dodajemy do pustej tablicy liczbę pomnożoną przez 2. W naszej tablicy lądują liczby 2,4,6…20.

Możemy to zrobić w pętli for, jeżeli bardzo nam zależy:

$arr = array();
for($num=1; $num <=10; $num++)
    $arr[] = $num * 2;

print_r($arr);
// Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 [5] => 12 [6] => 14 [7] => 16 [8] => 18 [9] => 20 )

Trzymajmy się jednak pierwszego, bardziej czytelnego przykładu. Zróbmy z niego funkcję, która pozwoli nam na stworzenie tablicy z liczbami z pewnego zakresu, pomnożonymi przez 2:

function arr_times_two($start, $stop){
    $arr = array();
    foreach(range($start, $stop) as $num)
        $arr[] = $num * 2;
    return $arr;
}
$arr1 = arr_times_two(10,15);
print_r($arr1);
//Array ( [0] => 20 [1] => 22 [2] => 24 [3] => 26 [4] => 28 [5] => 30 )

Przyjmujemy dwa argumenty, start i stop. Tworzymy pustą tablicę.

W zakresie od start do stop przechodzimy w pętli i do tablicy dodajemy liczbę razy dwa. Zwracamy tablicę.

Używamy naszej funkcji, aby wygenerować tablicę liczb od 10 do 15 włącznie pomnożonych przez 2, co otrzymujemy.

Poznaliśmy dzisiaj naprawdę dużo. Naukę będziemy kontynuować.