4. PHP – instrukcje sterujące – instrukcje warunkowe, wyboru oraz operator warunkowy


Instrukcje warunkowe

TaskQuest

Dodatek

Szybki quiz – przypomnienie poprzedniej lekcji

1. Które nazwy zmiennych są poprawne w PHP?

a) $2liczba b) $_licznik c) $moja zmienna d) $imieUzytkownika e) $xp-max

2. Co zostanie wyświetlone?

$a = 7;
$b = 2;
echo $a % $b . "<br>";
echo $a ** $b . "<br>";
echo $a / $b;

3. Co zostanie wyświetlone?

$e = 5;
echo $e++;
echo $e;
echo ++$e;

4. Jaki będzie wynik?

var_dump(10 == "10");
var_dump(10 === "10");

5. Co zostanie wyświetlone?

$x = 10;
$y = 3;
echo $x . $y . "<br>";
echo $x + $y;

6. Jaki będzie wynik każdego var_dump()?

$a = 10;
$b = 2;
var_dump($a > 5 && $b > 5);
var_dump($a > 5 || $b > 5);
var_dump($a > 5 xor $b < 5);

7. Ile wynosi $a po wykonaniu kodu?

$a = 5;
$b = &$a;
$b = 9;

8. Co się stanie po uruchomieniu tego kodu?

const XP_NA_POZIOM = 100;
XP_NA_POZIOM = 200;

9. (TaskQuest) Co wyświetli ten kod i dlaczego w projekcie jest to problem?

$poziom = 1;
echo "Do poziomu " . ++$poziom . "<br>";
echo "Twój poziom: $poziom";
Odpowiedzi

Szybki quiz – poprzednia lekcja

  1. Poprawne: b i d. $2liczba – zaczyna się od cyfry, $moja zmienna – spacja, $xp-max – minus jest operatorem, nie częścią nazwy.
  2. 1, 49, 3.5 (reszta z dzielenia, potęgowanie, dzielenie zwraca ułamek).
  3. 567 – $e++ najpierw zwraca 5, potem zwiększa; echo $e daje 6; ++$e najpierw zwiększa do 7, potem zwraca.
  4. bool(true), bool(false) – wartości równe, ale typy różne (int i string).
  5. 103 (łączenie tekstów kropką), 13 (dodawanie).
  6. bool(false), bool(true), bool(false) – przy xor oba warunki są prawdziwe, więc wynik to false.
  7. 9 – $b jest referencją do $a, więc zmiana $b zmienia $a.
  8. Błąd składni (parse error) – stałej nie można przypisać nowej wartości.
  9. „Do poziomu 2” i „Twój poziom: 2”. ++$poziom trwale zmienia zmienną, więc od tej linii użytkownik „ma” poziom 2, choć nie awansował. Zamiast tego: ($poziom + 1). Ważne w tej lekcji – jeśli taki zapis został w projekcie, zepsuje logikę awansu.

if, else, elseif

Instrukcje warunkowe (if, else, elseif), instrukcje wyboru (switch, match) oraz operatory warunkowe pozwalają programowi podejmować decyzje i wykonywać różne fragmenty kodu w zależności od spełnienia określonych warunków. Najprościej mówiąc – odpowiadają na pytania „co jeżeli?”.

Podam wam teraz prosty przykład:

Jeżeli liczba jest większa od zera, to wypisz że jest dodatnia

zapis tego stwierdzenia za pomocą instrukcji if będzie wyglądał następująco:

if($liczba>0) echo "jest dodatnia";

Jeżeli potrzebujemy rozwinąć naszą myśl o zapytanie „a co gdy warunek nie jest spełniony?” – używamy else.

Jeżeli liczba jest większa od zera, to wypisz że jest dodatnia – w przeciwnym wypadku napisz, że nie jest dodatnia

if($liczba>0) {
echo "jest dodatnia";
}
else {
echo "nie jest dodatnia";
}

Oczywiście instrukcje możemy zagnieżdżać jedna w drugiej.

Może zajść sytuacja, że przed użyciem else chcemy sprawdzić jeszcze jakieś inne warunki, wtedy przychodzi nam z pomocą instrukcja elseif.

if($liczba>0) 
{
echo "jest dodatnia";
}
elseif($liczba==0)
{
echo "liczba jest zerem";
}
else
{
echo "jest ujemna";
}

Ważne: Instrukcje można zagnieżdżać jedna w drugiej.

UWAGA! w instrukcji warunkowej nie używamy operatora „=” (operator przypisania). Używamy „==” (dwa znaki =) lub „===” (trzy znaki =)

switch

Gdy wiemy, że nasza zmienna będzie przyjmowała jakieś konkretne wartości, możemy użyć wtedy instrukcji switch.

switch ($plec) {
case "K":
echo "Kobieta";
break;
case "M":
echo "Mężczyzna";
break;
default:
echo "Nierozpoznany wybór";
break;
}

break; używamy by przerwać działanie instrukcji, gdy warunek zostanie spełniony.

default; oznacza akcję domyślą, gdy żaden z warunków nie zostanie spełniony.

UWAGA!  Switch używa luźnego porównania (==), co może prowadzić do niespodziewanych rezultatów przy porównywaniu typów.

 Wyrażenie match (PHP 8.0+)

Match to nowoczesna alternatywa dla switch, wprowadzona w PHP 8.0. Jest bezpieczniejsza i bardziej zwięzła:

$kolor = match ($status) {
    'draft' => 'gray',
    'published' => 'green',
    'archived' => 'red',
    default => 'black',
};

Różnice między switch a match:

Cecha switch match
Porównanie Luźne (==) Ścisłe (===)
Zwraca wartość Nie Tak
Wymaga break Tak Nie
Fall-through Tak Nie

Przykład z wieloma warunkami:

$statusCode = 404;
$komunikat = match($statusCode) {
    200, 201, 204 => "Sukces",
    400, 404 => "Błąd klienta",
    500, 502, 503 => "Błąd serwera",
    default => "Nieznany status"
};
echo $komunikat;

Match z wyrażeniami:

$wiek = 25;
$kategoria = match(true) {
    $wiek < 13 => "dziecko",
    $wiek < 18 => "nastolatek",
    $wiek < 65 => "dorosły",
    default => "senior"
};
echo $kategoria;

Dlaczego match jest lepsze?

  • Zwraca wartość: match jest wyrażeniem (expression), co oznacza, że możesz przypisać jego wynik bezpośrednio do zmiennej lub użyć go w instrukcji return.
  • Brak potrzebny break: Nie musisz pisać break przy każdym przypadku. Kod nie „wpada” automatycznie w kolejne bloki (brak efektu fall-through), co eliminuje częste błędy.
  • Ścisłe porównanie (===): switch używa luźnego porównania (==), co może prowadzić do niespodzianek (np. 0 == 'tekst' w starych wersjach PHP zwracało true). match porównuje rygorystycznie – sprawdza zarówno wartość, jak i typ.
  • Wymóg obsłużenia wszystkich opcji: Jeśli match nie dopasuje żadnej wartości i nie zdefiniujesz bloku default, PHP wyrzuci błąd (UnhandledMatchError). Dzięki temu trudniej przeoczyć błąd w kodzie.
  • Łączenie warunków: Możesz łatwo połączyć kilka warunków po przecinku:
     
$wynik = match ($rola) { 
    'admin', 'editor' => 'ma dostęp', 
    'guest' => 'brak dostępu', 
};

Kiedy nadal warto używać switch?

Użyj switch, jeśli w danym bloku case musisz wykonać złożoną logikę wielolinijkową (kilka operacji, pętli itp.).
Wyrażenie match pozwala na wykonanie tylko jednego wyrażenia po strzałce =>

Alternatywna składnia if i switch

Można zastąpić nawias { znakiem : i zamiast zamykającego } użyć odpowiednio endif; lub endswitch;

Przykład dla if:

if ($a == 5):
    echo "a jest równe 5";
    echo "...";
elseif ($a == 6):
    echo "a jest równe 6";
    echo "!!!";
else:
    echo "a nie jest 5 ani 6";
endif;

Przykład dla switch:

switch ($plec):
case "K":
echo "Kobieta";
break;
case "M":
echo "Mężczyzna";
break;
default:
echo "Nierozpoznany wybór";
break;
endswitch;

Ta forma zapisu jest bardzo rzadko spotykana i używana głównie w szablonach mieszających PHP z HTML.

Operator warunkowy (ternary)

Operator warunkowy to skrócona forma instrukcji if…else, która zwraca wartość:

$wiek = 20;
$status = ($wiek >= 18) ? "pełnoletni" : "niepełnoletni";
echo $status; // wypisze: pełnoletni

Składnia: (warunek) ? wartość_jeśli_prawda : wartość_jeśli_fałsz

Zagnieżdżone operatory:

$ocena = 85;
$wynik = ($ocena >= 90) ? "celujący" 
       : ($ocena >= 75) ? "bardzo dobry"
       : ($ocena >= 60) ? "dobry"
       : "dostateczny";

Null Coalescing Operator (PHP 7.0+)

Operator ?? sprawdza, czy zmienna istnieje i nie jest null:

// Stary sposób:
$nazwa = isset($_GET['nazwa']) ? $_GET['nazwa'] : 'Gość';

// Nowy sposób (PHP 7.0+):
$nazwa = $_GET['nazwa'] ?? 'Gość';

// Łańcuchowe sprawdzanie (PHP 7.0+):
$config = $userConfig ?? $defaultConfig ?? 'brak';

Spaceship Operator (PHP 7.0+)

Operator <=> służy do porównywania wartości:

$a = 10;
$b = 5;

echo $a <=> $b; // zwraca 1 (gdy a > b)
echo $b <=> $a; // zwraca -1 (gdy b < a)
echo $a <=> $a; // zwraca 0 (gdy a == b)

// Przydatny przy sortowaniu:
usort($array, fn($a, $b) => $a <=> $b);

Zadania do wykonania:

Zadanie 1: Napisz program sprawdzający czy liczba jest parzysta.

Rozwiązanie:
$a = 5;	
if ($a == 0) {
echo 'podałeś 0';
} elseif ($a % 2 == 0) {
echo 'parzysta';
} else {
echo 'nieparzysta';
}

Zadanie 2: Porównaj ze sobą 2 dowolne liczby i wypisz która jest większa.

Rozwiązanie:
echo "<u>Zadanie 2: Porównaj ze sobą 2 dowolne liczby i wypisz która jest większa.</u><br><br>";
$a = 10;
$b = 5;

echo "Porównujemy liczby $a i $b<br>";
if ($a > $b) {
echo "większa jest liczba a = $a";
} elseif ($b > $a) {
echo "większa jest liczba b = $b";
} else {
echo "liczby są równe";
}

//rozwiązanie z match
$wynik = match(true) {
$a > $b => "większa jest liczba a = $a",
$b > $a => "większa jest liczba b = $b",
default => "liczby są równe"
};
echo $wynik;

Zadanie 3: Porównaj ze sobą 4 nie równe sobie liczby i wypisz największą.

Rozwiązanie:
echo "<u>Zadanie 3: Porównaj ze sobą 4 nierówne sobie liczby i wypisz największą.</u><br><br>";
$a = 10;
$b = 5;
$c = 18;
$d = 1;
$max = $a;

echo "Porównujemy liczby: $a, $b, $c, $d<br>";

if ($b > $max) { $max = $b; }
if ($c > $max) { $max = $c; }
if ($d > $max) { $max = $d; }

echo "największa z liczb to $max";

Zadanie 4: Porównaj ze sobą 3 nie równe sobie liczby i wypisz je w kolejności od największej do najmniejszej.

Rozwiązanie:
echo "<u>Zadanie 4: Porównaj ze sobą 3 nierówne sobie liczby i wypisz je w kolejności od największej do najmniejszej.</u><br><br>";
$a = 10;
$b = 5;
$c = 18;

echo "Porównujemy liczby: $a, $b, $c<br>";

// Szukamy najmniejszej
$min = $a;
if ($b < $min) { $min = $b; }
if ($c < $min) { $min = $c; }

// Szukamy największej
$max = $a;
if ($b > $max) { $max = $b; }
if ($c > $max) { $max = $c; }

// Środkowa to ta, która nie jest ani min ani max
if ($a != $min && $a != $max) { $mid = $a; }
if ($b != $min && $b != $max) { $mid = $b; }
if ($c != $min && $c != $max) { $mid = $c; }

echo "Liczby posortowane: $max, $mid, $min";

Zadanie 5: Porównaj ze sobą 4 nie równe sobie liczby i wypisz je w kolejności od największej do najmniejszej.

Rozwiązanie:
echo "<u>Zadanie 5: Porównaj ze sobą 4 nierówne sobie liczby i wypisz je w kolejności od największej do najmniejszej.</u><br><br>";
$a = 10;
$b = 5;
$c = 18;
$d = 1;

echo "Porównujemy liczby: $a, $b, $c, $d<br>";

// Szukamy najmniejszej
if ($a < $b && $a < $c && $a < $d) {
$l1 = $a;
} elseif ($b < $a && $b < $c && $b < $d) {
$l1 = $b;
} elseif ($c < $a && $c < $b && $c < $d) {
$l1 = $c;
} else {
$l1 = $d;
}

// Szukamy największej
$l4 = $a;
if ($b > $l4) { $l4 = $b; }
if ($c > $l4) { $l4 = $c; }
if ($d > $l4) { $l4 = $d; }

// Szukamy dwóch środkowych
$m2 = null;
if ($a != $l1 && $a != $l4) {
$m1 = $a;
$m2 = empty($m2) ? $a : $m2;
}
if ($b != $l1 && $b != $l4) {
$m1 = $b;
$m2 = empty($m2) ? $b : $m2;
}
if ($c != $l1 && $c != $l4) {
$m1 = $c;
$m2 = empty($m2) ? $c : $m2;
}
if ($d != $l1 && $d != $l4) {
$m1 = $d;
}

$l2 = ($m1 > $m2) ? $m2 : $m1;
$l3 = ($m1 < $m2) ? $m2 : $m1;

echo "Liczby posortowane: $l4, $l3, $l2, $l1";

Zadanie 6: Napisz program potrafiący rozwiązywać równanie kwadratowe: y = ax2 + bx + c. Przypominamy, że ilość rozwiązań zależy od wartości tzw. współczynnika Δ (Δ = b2 − 4ac).

Rozwiązanie:
echo "<u>Zadanie 6: Napisz skrypt, obliczający pierwiastki trójmianu kwadratowego ax<sup>2</sup> + bx + c = 0.	Za obliczanie pierwiastka kwadratowego odpowiada funkcja sqrt(\$zmienna)</u></br></br>";	
$a = 1;
$b = 2;
$c = 1;
$delta = $b * $b - 4 * $a * $c; //obliczamy wg wzoru
if ($delta > 0)
{
$x1 = (-$b - sqrt($delta)) / (2 * $a); //sqrt() pierwiastek kwadratowy
$x2 = (-$b + sqrt($delta)) / (2 * $a);
echo ' posiada dwa pierwiastki x1 = '.$x1.', x2 = '.$x2;
}
else if ($delta == 0)
{
$x = -$b / 2 * $a;
echo ' posiada jeden pierwiastek x = '.$x;
}
else echo ' nie posiada pierwiastków';

Zadanie 7: Zrealizuj kalkulator, który dla zadanych liczb w zależności od wartości zmiennej $wybor wykonuje: mnożenie, dzielenie, odejmowanie, dodawanie. Użyj instrukcji „switch”.

Rozwiązanie:
echo "<u>Zadanie 7: Kalkulator</u><br><br>"; 
$liczba1 = 4;
$liczba2 = 2;
$wybor = '/';

switch ($wybor) {
case "+":
echo $liczba1 + $liczba2;
break;
case "-":
echo $liczba1 - $liczba2;
break;
case "*":
echo $liczba1 * $liczba2;
break;
case "/":
if ($liczba2 != 0) {
echo $liczba1 / $liczba2;
} else {
echo "Błąd: dzielenie przez zero!";
}
break;
default:
echo "Nieznana operacja";
break;
}

//rozwiązanie z match
$wynik = match($wybor) {
"+" => $liczba1 + $liczba2,
"-" => $liczba1 - $liczba2,
"*" => $liczba1 * $liczba2,
"/" => $liczba2 != 0 ? $liczba1 / $liczba2 : "Błąd: dzielenie przez zero!",
default => "Nieznana operacja"
};
echo $wynik;

Zadanie 8: Napisz program, który dla danego punktu na płaszczyźnie sprawdzi, w której ćwiartce układu współrzędnych się on znajduje. Może jednak być tak, że punkt nie znajduje się w żadnej ćwiartce – leży na jednej z osi lub w środku układu współrzędnych. Wówczas program powinien to stwierdzić. Na wejściu znajdują się dwie liczby całkowite oddzielone spacją, x i y(−1 000 000 000≤x, y≤1 000 000 000), oznaczające współrzędne danego punktu. Jeżeli podany punkt nie leży na żadnej z osi, Twój program powinien wypisać: I, II, III lub IV, w przypadku gdy punkt należy do, odpowiednio, pierwszej, drugiej, trzeciej lub czwartej ćwiartki układu współrzędnych. Jeżeli punkt leży w środku układu współrzędnych, program powinien wypisać liczbę 0. W przeciwnym razie, program powinien wypisać OX (duże O i duże X), jeśli punkt leży na osi X, a OY – jeśli punkt leży na osi Y.
Przykład
Dla danych wejściowych:
5 7
poprawnym wynikiem jest:
I
a dla danych wejściowych:
0 -1000000000
poprawnym wynikiem jest:
OY
natomiast dla danych wejściowych:
0 0

Zadanie 9: Twoim zadaniem jest stwierdzić, czy z trzech odcinków o podanych długościach można zbudować trójkąt o dodatnim polu. Pierwszy i jedyny wiersz wejścia zawiera trzy liczby naturalne a,b,c(1≤a, b, c≤1 000 000 000), oddzielone spacjami. Liczby te oznaczają długości trzech odcinków. Twój program powinien wypisać jedno słowo TAK lub NIE, w zależności od tego, czy z odcinków o długościach takich jak na wejściu można zbudować niezdegenerowany trójkąt, czyli trójkąt o dodatnim polu.
Przykład
Dla danych wejściowych:
8 7 5
poprawnym wynikiem jest:
TAK
a dla danych wejściowych:
1 10 2
poprawnym wynikiem jest:
NIE
oraz dla danych wejściowych:
4 4 8
poprawnym wynikiem jest:
NIE

Zadanie 10: Napisz instrukcję switch wyświetlającą na podstawie zmiennej całkowitej „nr” nazwę miesiąca słownie.
Zadanie 11: Napisz instrukcje która na podstawie zmiennej całkowitej ocena wyświetla jedna z informacji: brak promocji do następnej klasy, promocja do następnej klasy, promocja z oceną celującą.
Zadanie 12: Napisz instrukcję switch, która dla przekazanej jako parametr całkowity oceny wyświetli ją słownie.
Zadanie 13: Napisz instrukcję switch, która wczytuje kwotę w złotych, a następnie przelicza ją na taka walutę jaką wybierze użytkownik: funty, dolary, euro….
Zadanie 14: Napisz instrukcję switch, która przelicza metry na inne jednostki miary.
 
Zadanie 15: Napisz skrypt, który sprawdzi, czy zmienna $x jest większa od liczby 20 (użyj instrukcji warunkowej if)

Zadanie 16: Napisz skrypt, który sprawdzi, czy zmienna $z jest liczbą trzycyfrową (użyj instrukcji warunkowej if)

Zadanie 17: Napisz skrypt, który w zależności od wartości zmiennej $age umieszcza odpowiedni napis na stronie:

• jeżeli $wiek mniejszy od 18, wyświetl: „Jeszcze nie możesz głosować”
• jeżeli $wiek większy lub równy 18, wyświetl: „Możesz tylko głosować”
• jeżeli $wiek większy lub równy 21, wyświetl: „Możesz głosować i kandydować do Sejmu”
• jeżeli $wiek większy lub równy 30, wyświetl: „Możesz głosować i kandydować do Sejmu i Senatu”
• jeżeli $wiek większy lub równy 35, wyświetl: „Możesz głosować, kandydować do Sejmu i Senatu oraz
na Prezydenta”
Zadanie zrealizuj za pomocą instrukcji warunkowej if oraz Switch

Zadanie 18: Napisz skrypt, używając instrukcji switch, który umieszcza na stronie odpowiednią liczbę znaków + (plus) w zależności od wartości zmiennej $ile:

  • jeżeli $ile równe 1: wyświetl: +
  • jeżeli $ile równe 2: wyświetl: ++
  • jeżeli $ile równe 3: wyświetl: +++
  • …
  • jeżeli $ile równe 9: wyświetl: +++++++++
  • jeżeli $ile mniejsze od 1 lub większe od 9: wyświetl: „Wartość poza zakresem”

Zadanie 19: Napisz skrypt, używając instrukcji switch, który umieszcza na stronie napis z numerem kwartału roku w od zmiennej $miesiac:

  • jeżeli $miesiac równe 1,2, lub 3: wyświetl: „Kwartał I”
  • jeżeli $miesiac równe 4,5, lub 6: wyświetl: „Kwartał II”
  • jeżeli $miesiac równe 7,8, lub 9: wyświetl: „Kwartał III”
  • jeżeli $miesiac równe 10,11, lub 12: wyświetl: „Kwartał IV”
  • jeżeli $miesiac mniejsze od 1 lub większe od 12: wyświetl: „Błędny numer miesiąca”

TaskQuest — Twój projekt na cały semestr

KARTA PRACY

Karta pracy

Projekt: TaskQuest — grywalizowana aplikacja do zarządzania zadaniami. Użytkownik loguje się, dodaje zadania, za ich wykonanie zdobywa punkty XP, awansuje na poziomy, zdobywa odznaki i widzi swoją pozycję w rankingu klasy. Każda lekcja rozbudowuje tę samą aplikację o nową funkcję.

PHP — instrukcje warunkowe, wybór, operator warunkowy

Cel lekcji

Nauczyć aplikację podejmować decyzje na podstawie danych.

Co dziś budujesz

Logikę awansu na poziom oraz tytuły zależne od poziomu.

Ważna uwaga o progu poziomu

Skoro $xp cały czas rośnie i się nie resetuje, to próg potrzebny do kolejnego poziomu też musi rosnąć — inaczej po awansie na poziom 2 użytkownik z 100 XP awansowałby na poziom 3 już przy 101 XP, co byłoby za łatwe. Dlatego próg do następnego poziomu liczymy jako $poziom * XP_NA_POZIOM (poziom 1→2 potrzeba 100 XP, poziom 2→3 potrzeba 200 XP, itd.).

Ograniczenie tej wersji: pojedynczy if sprawdza próg i awansuje tylko o jeden poziom na raz. Jeśli ktoś zdobędzie od razu bardzo dużo XP i „przeskoczy” dwa progi naraz, ten kod tego nie złapie w jednym uruchomieniu. To celowe uproszczenie — w lekcji 5 (pętle) zamienimy ten if na while, żeby awansować użytkownika o tyle poziomów, ile faktycznie mu się należy, za jednym razem.

Kroki do wykonania

  1. Oblicz próg kolejnego poziomu: $progNastepnegoPoziomu = $poziom * XP_NA_POZIOM;.
  2. Napisz warunek if: jeśli $xp >= $progNastepnegoPoziomu, zwiększ $poziom o 1 i wyświetl komunikat „Awansowałeś!”.
  3. Za pomocą switch przypisz użytkownikowi tytuł zależny od poziomu, np. 1 = Nowicjusz, 2 = Wojownik, 3 i więcej = Mistrz. Wyświetl tytuł użytkownika – od Ciebie zależy gdzie go umieścisz.
  4. Zdefiniuj zmienną $wykonalDzisiajZadanie — na razie ustaw ją ręcznie na true albo false, tylko po to, żeby przetestować działanie operatora warunkowego (prawdziwe sprawdzanie, czy użytkownik był dziś aktywny, zrobimy dopiero w lekcji 7, gdy poznamy obsługę dat).
  5. Za pomocą operatora warunkowego (?: lub ??) wyświetl na podstawie $wykonalDzisiajZadanie krótką etykietę statusu: „Aktywny” albo „Nieaktywny”.
  6. Zaktualizuj $procentPostepu z lekcji 3 — dotychczasowy wzór działał tylko dla poziomu 1. Teraz, gdy próg jest dynamiczny, policz procent postępu w obrębie aktualnego poziomu: $procentPostepu = (($xp – ($poziom – 1) * XP_NA_POZIOM) / XP_NA_POZIOM) * 100;. Od teraz w całym projekcie używamy tylko tej, uogólnionej wersji.
  7. Przetestuj różne wartości $xp (w tym taką, która przeskakuje próg) oraz obie wartości $wykonalDzisiajZadanie, żeby zobaczyć różne komunikaty.

Podpowiedzi / fragmenty kodu

<?php$progNastepnegoPoziomu = $poziom * XP_NA_POZIOM;
if ($xp >= $progNastepnegoPoziomu) {
    $poziom++;
    echo "Awansowałeś na poziom $poziom!";
}
switch ($poziom) {
    case 1:
        $tytul = "Nowicjusz";
        break;
    case 2:
        $tytul = "Wojownik";
        break;
    default:
        $tytul = "Mistrz";
}
// Tymczasowo ustawiane ręcznie - w lekcji 7 zastąpimy to sprawdzeniem daty
$wykonalDzisiajZadanie = true;
$status = $wykonalDzisiajZadanie ? "Aktywny" : "Nieaktywny";
echo "Status: $status";
// Uogólniona wersja procentu postępu - zastępuje wzór z lekcji 3
$procentPostepu = (($xp - ($poziom - 1) * XP_NA_POZIOM) / XP_NA_POZIOM) * 100;

?>

Do samodzielnego sprawdzenia

  • ☐ Próg kolejnego poziomu jest liczony wzorem ($poziom * XP_NA_POZIOM), a nie sztywną liczbą.
  • ☐ Zmiana wartości $xp faktycznie zmienia poziom i tytuł na stronie.
  • ☐ Rozumiem i potrafię wyjaśnić, dlaczego pojedynczy if nie obsłuży awansu o dwa poziomy naraz.
  • ☐ switch obsługuje co najmniej 3 przypadki plus default.
  • ☐ Etykieta statusu poprawnie zmienia się w zależności od $wykonalDzisiajZadanie.

Pytania kontrolne

  1. Dlaczego próg kolejnego poziomu musi rosnąć wraz z poziomem, a nie może być stałą liczbą?
  2. Co się stanie w powyższym kodzie, jeśli użytkownik z poziomu 1 (próg 100) zdobędzie od razu 250 XP? Ile poziomów awansuje po jednym uruchomieniu skryptu i dlaczego?
  3. Kiedy lepiej użyć switch zamiast wielu if/elseif?
  4. Co robi operator ?? i czym różni się od ?:?

PODSUMOWANIE LEKCJI

W skrócie

  • if sprawdza warunki po kolei, od góry. Wykonuje się tylko pierwszy spełniony blok – kolejne elseif i else są pomijane. Dlatego przy przedziałach (punkty, wiek, XP) kolejność warunków ma znaczenie.
  • W warunku porównujemy przez == lub ===. Pojedyncze = to przypisanie – kod się uruchomi, ale zrobi coś innego, niż chcesz.
  • switch porównuje luźno (==) i bez break „przelatuje” do kolejnych case (fall-through). default wykonuje się, gdy nic nie pasuje.
  • match porównuje ściśle (===) – "5" (tekst) to nie to samo co 5 (liczba). Nie potrzebuje break.
  • match zwraca wartość – zapisujesz ją do zmiennej albo od razu wyświetlasz. Po => może być tylko jedno wyrażenie.
  • match bez default, który nie znajdzie dopasowania, kończy skrypt błędem UnhandledMatchError.
  • match(true) pozwala sprawdzać przedziały ($wiek < 18 => ...) – wygrywa pierwszy prawdziwy warunek.
  • Operator warunkowy warunek ? A : B to skrócone if…else, które zwraca wartość. Stosuj go do prostych decyzji, a nie do rozbudowanej logiki.
  • Zagnieżdżony operator warunkowy w PHP 8 musi mieć nawiasy wokół wewnętrznego wyrażenia. Zapis a ? b : c ? d : e bez nawiasów kończy się błędem krytycznym. Przy wielu przedziałach czytelniejsze jest if/elseif albo match(true).
  • ?? zwraca lewą stronę, jeśli zmienna istnieje i nie jest null, w przeciwnym razie prawą. Nie reaguje na 0, "" czy false – dla nich zwraca lewą stronę.
  • <=> zwraca -1, 0 lub 1 – nie true/false.
  • Składnia alternatywna (: + endif; / endswitch;) działa tak samo jak klamry – różni się tylko zapisem.

Co trzeba umieć na INF.03?

  • napisać instrukcję if / elseif / else dla podanego opisu słownego („jeżeli…, w przeciwnym razie…”),
  • ustawić warunki w poprawnej kolejności przy sprawdzaniu przedziałów,
  • połączyć kilka warunków operatorami &&, ||, !,
  • użyć wartości domyślnej, gdy dane nie zostały przesłane: $_GET['klucz'] ?? wartość lub zapis z isset() i operatorem warunkowym (oba zapisy są pokazane w lekcji),
  • rozpoznać błąd = zamiast == w warunku,
  • czytać cudzy kod z if i switch i przewidzieć jego wynik.

Minimum, które powinno wejść w pamięć

Jeżeli masz zapamiętać tylko kilka rzeczy z tej lekcji, zapamiętaj te:

  1. W warunku == albo ===, nigdy =.
  2. if/elseif – wykonuje się tylko pierwszy spełniony warunek. Przedziały sprawdzaj od najbardziej szczegółowego (np. od największego progu).
  3. switch – każdy case kończ break;, na końcu default.
  4. match – ścisłe porównanie, zwraca wartość, kończy się średnikiem };, dodawaj default.
  5. $x = warunek ? "tak" : "nie"; – jedna decyzja, jedna linia.
  6. $id = $_GET['id'] ?? 6; – wartość domyślna, gdy brak danych.
  7. Zagnieżdżony operator warunkowy tylko z nawiasami – albo zamień go na if/elseif.

Ściągawka – najważniejsze polecenia i składnia

// if / elseif / else
if ($xp >= 200) {
    // ...
} elseif ($xp >= 100) {
    // ...
} else {
    // ...
}

// switch – luźne porównanie (==), potrzebny break
switch ($poziom) {
    case 1:
        $tytul = "Nowicjusz";
        break;
    case 2:
        $tytul = "Wojownik";
        break;
    default:
        $tytul = "Mistrz";
}

// match – ścisłe porównanie (===), zwraca wartość
$tytul = match ($poziom) {
    1 => "Nowicjusz",
    2 => "Wojownik",
    3, 4, 5 => "Mistrz",      // kilka wartości po przecinku
    default => "Legenda",
};

// match(true) – przedziały
$kategoria = match (true) {
    $wiek < 18 => "niepełnoletni",
    default => "pełnoletni",
};

// operator warunkowy
$status = $aktywny ? "Aktywny" : "Nieaktywny";

// zagnieżdżony – tylko z nawiasami (PHP 8)
$opis = $xp >= 200 ? "dużo" : ($xp >= 100 ? "średnio" : "mało");

// ?? – wartość domyślna, gdy brak / null
$id = $_GET['id'] ?? 6;

// <=> – zwraca -1, 0 lub 1
echo 3 <=> 7;   // -1

// składnia alternatywna
if ($a == 5):
    echo "pięć";
else:
    echo "nie pięć";
endif;
KonstrukcjaPorównanieZwraca wartośćbreakKiedy
if/elseif/elsedowolny waruneknie–przedziały, złożone warunki, kilka instrukcji w bloku
switch==nietakwiele konkretnych wartości, kilka instrukcji w case
match===taknieprzypisanie wartości zależnej od konkretnej wartości
? :dowolny warunektak–prosta decyzja „albo–albo”
??czy istnieje i nie nulltak–wartość domyślna

Quiz – sprawdź się

1. Uczeń ma 95 punktów. Co wyświetli kod? Jak go poprawić, żeby wyświetlił „bardzo dobry”?

$punkty = 95;
if ($punkty >= 50) echo "dostateczny";
elseif ($punkty >= 75) echo "dobry";
elseif ($punkty >= 90) echo "bardzo dobry";

2. Dlaczego ten kod zawsze wyświetla „Admin”, niezależnie od wartości $rola? Jaka będzie wartość $rola po wykonaniu kodu?

$rola = "gość";
if ($rola = "admin") {
    echo "Admin";
}

3. Co zostanie wyświetlone? Co należy dopisać, aby wyświetlało się tylko „Wojownik”?

$poziom = 2;
switch ($poziom) {
    case 1: echo "Nowicjusz ";
    case 2: echo "Wojownik ";
    case 3: echo "Mistrz ";
    default: echo "Nieznany";
}

4. Co wyświetli match, a co wyświetliłby switch z tym samym case 5? Z czego wynika różnica?

$ocena = "5";
echo match ($ocena) {
    5 => "bardzo dobry",
    default => "inna",
};

5. Co się stanie po uruchomieniu tego kodu? Jak to naprawić?

$dzien = 8;
$nazwa = match ($dzien) {
    1 => "poniedziałek",
    2 => "wtorek",
    // ... pozostałe dni ...
    7 => "niedziela",
};

6. Uzupełnij lukę, aby dla soboty i niedzieli wynikiem było „weekend”.

$typ = match ($dzien) {
    __________ => "weekend",
    default => "dzień roboczy",
};

7. Co zostanie wyświetlone?

$temp = 18;
echo match (true) {
    $temp < 0 => "mróz",
    $temp < 15 => "zimno",
    $temp < 25 => "ciepło",
    default => "upał",
};

8. Zapisz ten kod w jednej linii za pomocą operatora warunkowego.

if ($xp >= 100) {
    $info = "awans";
} else {
    $info = "brak awansu";
}

9. Co zostanie wyświetlone?

$imie = null;
echo $imie ?? "Gość";
echo "<br>";
$wiek = 0;
echo $wiek ?? 18;

10. Napisz jedną linię kodu, która zapisze do zmiennej $idKontynentu wartość przesłaną metodą GET w parametrze kontynent, a jeżeli parametr nie został przesłany – wartość 6. Podaj dwa sposoby.

11. Ten kod w PHP 8 kończy się błędem krytycznym. Dlaczego? Popraw go.

$opis = $xp >= 200 ? "dużo" : $xp >= 100 ? "średnio" : "mało";

12. Która wersja jest poprawna?

a)

if ($a == 5):
    echo "pięć";
end if;

b)

if ($a == 5):
    echo "pięć";
endif;

c)

if ($a == 5):
    echo "pięć";
}

13. Co wyświetli echo 3 <=> 7;?

14. Kiedy lepiej użyć switch zamiast match? Odpowiedz jednym zdaniem.

15. (TaskQuest) Użytkownik ma $poziom = 1, XP_NA_POZIOM = 100 i zdobył od razu $xp = 250. Uruchamiasz kod z karty pracy (próg, if, switch, nowy wzór na $procentPostepu). Jakie wartości będą miały $poziom, $tytul i $procentPostepu? Co ten wynik mówi o ograniczeniu pojedynczego if?


Odpowiedzi
  1. Wyświetli „dostateczny”, bo pierwszy warunek (>= 50) jest już spełniony i reszta jest pomijana. Poprawka: sprawdzać od największego progu – >= 90, potem >= 75, potem >= 50.
  2. = to przypisanie, nie porównanie. Do $rola trafia "admin", a niepusty tekst w warunku jest traktowany jako prawda. Po wykonaniu $rola ma wartość "admin". Poprawnie: if ($rola == "admin").
  3. „Wojownik Mistrz Nieznany” – brak break, więc po dopasowaniu case 2 wykonują się wszystkie kolejne bloki. Należy dopisać break; po każdym echo.
  4. match wyświetli „inna”, bo "5" (string) !== 5 (int). switch wyświetliłby „bardzo dobry”, bo porównuje luźno (==).
  5. Błąd krytyczny UnhandledMatchError – żadna gałąź nie pasuje do 8, a nie ma default. Naprawa: dodać np. default => "błędny numer dnia",.
  6. "sobota", "niedziela"
  7. „ciepło” – pierwszy prawdziwy warunek to $temp < 25.
  8. $info = ($xp >= 100) ? "awans" : "brak awansu";
  9. „Gość” oraz 0. ?? reaguje tylko na null lub nieistniejącą zmienną – 0 to poprawna wartość, więc zostaje wyświetlona.
  10. $idKontynentu = $_GET['kontynent'] ?? 6;
    albo $idKontynentu = isset($_GET['kontynent']) ? $_GET['kontynent'] : 6;
  11. PHP 8 nie pozwala zagnieżdżać operatora warunkowego bez nawiasów, bo kolejność wykonania byłaby niejednoznaczna. Poprawnie:
    $opis = $xp >= 200 ? "dużo" : ($xp >= 100 ? "średnio" : "mało");
  12. b – składnia alternatywna kończy się endif; (jedno słowo, ze średnikiem).
  13. -1 (lewa wartość jest mniejsza).
  14. Gdy w danym przypadku trzeba wykonać kilka instrukcji (złożoną logikę), bo po => w match może być tylko jedno wyrażenie.
  15. $poziom = 2, $tytul = "Wojownik", $procentPostepu = 150. Pojedynczy if awansuje tylko o jeden poziom, chociaż 250 XP wystarcza na poziom 3 (próg 200). Procent większy niż 100 pokazuje, że użytkownik „utknął” poniżej należnego poziomu – naprawimy to pętlą while w lekcji 5.