Tym razem pochylimy się nad niektórymi elementami konstrukcji tego języka, które mogły nam wcześniej umknąć i warto je poznać zanim pójdziemy dalej.

Będą to:

  • funkcje z dowolną liczbą argumentów
  • switch statement
  • match statement

Do dzieła.

Funkcje – argumenty domyślne

Argumenty domyślne to takie, których nie musimy wcale podawać do funkcji, ponieważ mają już jakąś ustaloną, domyślną wartość i podajemy je tylko wtedy, gdy chcemy uzyskać inną wartość bądź zachowanie.

Zobaczmy najpierw przykład poniższej funkcji:

<?php
function normalize_name($name){
    $name = trim($name);
    return ucfirst(strtolower($name));
}
$login = "   jOHn";
echo normalize_name($login);
//John

Funkcja ta normalizuje jakiś login. Na początku mamy zrobiony trim, czyli pozbawienie niepotrzebnych spacji po lewej i prawej stronie. Później mamy obniżenie wszystkiego do małej litery i podniesienie do wielkiej tylko pierwszej.

Dodajmy sobie do tej funkcji argument domyślny, określający czy chcemy, czy nie chcemy wykonać trim:

<?php
function normalize_name($name, $trim_name = true){
    if($trim_name){
        $name = trim($name);
    }
    
    return ucfirst(strtolower($name));
}
$login = "   jOHn";
echo normalize_name($login);
//John
echo normalize_name($login, false);
//john

Argument domyślny trim_name ustawiony na true. Jeżeli ten argument ma wartość true (blok warunkowy) to wykonamy trim. Jeżeli nie, przekażemy tam false – nie wykonamy trim.

Co prawda przeglądarka sama formatuje spacje jeszcze w określony sobie sposób, więc tych spacji nie widać poza pierwszą, ale imię jest zapisane małą literą, bo litera 'j’ nie była pierwsza i na nią ucfirst nie miało żadnego efektu.

Jest to tylko prosty przykład jak używać argumentów domyślnych. Czy chcemy ich używać i znajdujemy dla nich zastosowanie – to już nasza sprawa.

Variadic function – dowolna ilość argumentów

Zobaczmy sobie na taką funkcję i zastanówmy się, co jest jej argumentami:

function sum($a, $b)
{
    return $a + $b;
}
echo sum(2,3);
//5

Oczywiście argumentami są a i b (2 i 3 w wywołaniu), argumenty są dwa.

Co jeżeli potrzebujemy więcej argumentów? Możemy napisać taką funkcję, która przyjmuje tablicę (z dowolną ilością elementów) jako argument:

<?php
function sum($arr)
{
    $sum_output = 0;
    foreach($arr as $number)
    {
        $sum_output += $number;
    }
    return $sum_output;
}
echo sum([2,3]) . "</br>";
//5
echo sum([2,3,4,5]);
//14

Funkcja przyjmuje tablicę arr jako argument, posiada zmienną sum_output do której dodaje każdą liczbę z tablicy przekazanej jej i zwraca tę zmienną.

Dzięki temu możemy dodać do siebie dowolną ilość liczb.

Oczywiście jest to swego rodzaju wybieg – użytkownik musi wiedzieć, aby zawsze podawać argumenty jako tablicę (czyli tak na dobrą sprawę jeden argument w postaci tablicy zawierającej pewne elementy).

Możemy jednak chcieć podawać argumenty „normalnie”, po przecinku, a jednocześnie mieć ochotę na ich dowolną ilość.

Możemy to osiągnąć operatorem „…”:

<?php
function sum(...$nums)
{
    $sum_output = 0;
    foreach($nums as $number)
    {
        $sum_output += $number;
    }
    return $sum_output;
}
echo sum(2,3) . "</br>";
//5
echo sum(2,3,4,5);
//14

Jak widać niewiele się zmieniło w funkcji. Te „nums” z kropeczkami to de facto taka sama tablica i taki sam mechanizm.

Zmienił się jednak sposób przekazywania – teraz możemy dawać liczby po przecinku, w dowolnej ilości, zaś „…$nums” upakuje je do tablicy „$nums”, z której możemy korzystać.

Jest to tylko dla wygody osób, które z naszej funkcji korzystać będą. Aby jednak udowodnić, że „…$nums” pakuje nam te argumenty po przecinku podawane do jednej tablicy „$nums” zrobimy sobie ten przykład z użyciem funkcji array_sum:

<?php
function sum(...$nums)
{
    return array_sum($nums);
}
echo sum(2,3) . "</br>";
//5
echo sum(2,3,4,5);
//14

Funkcja array_sum bierze tablicę i zwraca sumę jej elementów. Zaś „…$nums” pozwala nam przekazywać do funkcji „po przecinku” różne elementy, które do tablicy „$nums” zostaną upakowane.

Wszystko dla wygody użytkownika. My z tego korzystać nie musimy, zwłaszcza jeżeli piszemy kod sami dla siebie i będziemy pamiętać, którym funkcjom przekazywać argument w postaci tablicy:

<?php
function sum($nums)
{
    return array_sum($nums);
}
echo sum([2,3]) . "</br>";
//5
echo sum([2,3,4,5]);
//14

Mimo wszystko pamięć ludzka bywa zawodna i funkcje ze zmienną ilością argumentów, które możemy przekazywać „po przecinku” są po prostu intuicyjne w użyciu.

Switch statement – alternatywa dla bloków warunkowych

Nieczęsto używamy ze „swticha”, ale warto go znać, ponieważ czasami się w kodzie pojawia i jest w stanie być bardziej czytelny od tradycyjnych bloków warunkowych.

Najlepiej zobrazować jak działa switch na przykładzie:

<?php
$i = random_int(0,3);
switch ($i) {
    case 0:
        echo "i equals 0";
        break;
    case 1:
        echo "i equals 1";
        break;
    case 2:
        echo "i equals 2";
        break;
    default:
       echo "i is not equal to 0, 1 or 2";
}

Losujemy liczbę od 0 do 3 (włącznie) i przypisujemy ją do zmiennej. Następnie zmienną wrzucamy w switch.

Switch jest blokiem kodu, który ma „case” z wartością oraz „default” czyli co robić, gdy zmienna nie odpowiada żadnej wartości.

Każdy „case” ma wartość, do której porównujemy zmienną i pewien blok kodu, zakończony słówkiem „break”.

Na początek może wyglądać mało intuicyjnie, ale gdy poznamy tę konwencję sami możemy zdecydować, czy to nam odpowiada, czy bloki if:

<?php
$i = random_int(1,3);
if($i === 0){
    echo "i equals 0";
}
elseif($i === 1){
    echo "i equals 1";
}
elseif($i === 2){
    echo "i equals 2";
}
else{
    echo "i is not 0,1 or 2";
}

Tutaj może się wydawać, że „if” jest czytelniejszy, a w takich jednolinijkowych blokach może być jeszcze czytelniejszy, gdy pozbawimy go nawiasów klamrowych:

<?php
$i = random_int(1,3);
if($i === 0)
    echo "i equals 0";

elseif($i === 1)
    echo "i equals 1";

elseif($i === 2)
    echo "i equals 2";

else
    echo "i is not 0,1 or 2";

Zobaczmy jednak na ten przykład:

<?php
$i = random_int(1,3);
if($i === 0 || $i === 1 || $i === 2)
    echo "i equals 0,1 or 2";
else
    echo "i is not 0,1 or 2";


?>

Mamy tutaj operator logiczny „||” czyli „lub”. Warunek jest, że zmienna ma być równa albo 0, albo 1, albo 2. Zmienna jest krótka i warunek też, natomiast namnażają się nam te byty w nawiasach.

W pewnych przypadkach może być dużo czytelniej użyć switch, zwłaszcza że ma on tę zaletę, że można jeden blok kodu przypisać do kilku wartości:

<?php
$i = random_int(1,6);
switch ($i) {
    case 1:
    case 2:
    case 3:
        echo "i equals 1,2 or 3";
        break;
    case 4:
    case 5:
        echo "i equals 4 or 5";
        break;
    case 6:
        echo "i equals 6";
        break;
    default:
       echo "i is not a number in range 1-6";
    }

Match statement w PHP

Match statement to rzecz nowa w PHP i być może znajdziemy dla niej jakieś zastosowanie, albo zakochamy się w jej konstrukcji i będziemy ją używać jako alternatywę dla innych, klasycznych sposobów porównywania zmiennych do siebie i przypisywania im jakiegoś zachowania.

Najlepiej match zobrazować na przykładzie i albo spodoba się nam ta konstrukcja od razu, albo machniemy ręką i przejdziemy dalej, przynajmniej wiedząc jak ona działa.

<?php 
$foods = ['cake', 'bar', 'apple'];
$random_idx = array_rand($foods);
$random_food = $foods[$random_idx];

$return_value = match ($random_food) {
    'apple' => 'This food is an apple',
    'bar' => 'This food is a bar',
    'cake' => 'This food is a cake',
};

var_dump($return_value);
?>

Mamy tablicę foods. Losujemy z niej losowy indeks przy użyciu array_rand. Tworzymy zmienną random_food, która jest właśnie tym losowym elementem z tablicy foods (jeżeli array_rand nam zwróci 2 to random_food będzie miało wartość 'apple’).

Do zmiennej return_value przypisujemy match statement, który określa jaka wartość ma owocować jaką zawartością zwróconą do zmiennej.

Albo podoba nam się match, albo będziemy go po prostu unikać, natomiast warto wiedzieć, że taka konstrukcja istnieje.