Lekcja 5: Operatory w PHP
Witaj w piątej lekcji kursu PHP! Po solidnym zrozumieniu zmiennych i typów danych, nadszedł czas, aby nauczyć się, jak na nich operować. Służą do tego operatory – specjalne symbole lub słowa kluczowe, które wykonują określone działania na jednej, dwóch lub trzech wartościach (operandach). PHP oferuje bogaty zestaw operatorów do wykonywania operacji arytmetycznych, przypisania, porównania, logicznych, bitowych i wielu innych. Opanowanie operatorów jest kluczowe do pisania użytecznego i dynamicznego kodu.
Czym są operatory i operandy?
Operator to symbol, który mówi interpreterowi PHP, jaką operację ma wykonać. Na przykład symbol +
jest operatorem dodawania.
Operand to wartość lub zmienna, na której operator działa. W wyrażeniu $a + $b
, zmienne $a
i $b
są operandami.
Operatory można podzielić ze względu na liczbę operandów, które przyjmują:
- Operatory Unarne: Działają na jednym operandzie (np.
!$a
- negacja logiczna,++$a
- inkrementacja). - Operatory Binarne: Działają na dwóch operandach (np.
$a + $b
- dodawanie,$x = 5
- przypisanie). Jest to najczęstszy typ operatorów. - Operator Trójargumentowy (Ternary Operator): Działa na trzech operandach (np.
$warunek ? $wartosc_prawda : $wartosc_falsz
). W PHP jest tylko jeden taki operator.
Operatory Arytmetyczne
Operatory arytmetyczne służą do wykonywania podstawowych operacji matematycznych na liczbach.
Operator | Nazwa | Przykład | Wynik (dla $a=10, $b=3) | Opis |
---|---|---|---|---|
+ |
Dodawanie | $a + $b |
13 | Suma dwóch operandów. |
- |
Odejmowanie | $a - $b |
7 | Różnica dwóch operandów. |
* |
Mnożenie | $a * $b |
30 | Iloczyn dwóch operandów. |
/ |
Dzielenie | $a / $b |
3.333... | Iloraz dwóch operandów. Wynik jest zawsze typu float , chyba że oba operandy są liczbami całkowitymi, są podzielne bez reszty i wynik mieści się w zakresie typu int (rzadki przypadek, np. 4 / 2 da int(2) ). |
% |
Modulo (Reszta z dzielenia) | $a % $b |
1 | Reszta z dzielenia pierwszego operandu przez drugi. Operandy są konwertowane na liczby całkowite przed wykonaniem operacji. Znak wyniku jest taki sam jak znak dzielnej. |
** |
Potęgowanie (od PHP 5.6) | $a ** $b |
1000 | Pierwszy operand podniesiony do potęgi drugiego operandu. |
<?php
$a = 10;
$b = 3;
echo "Dodawanie: " . ($a + $b) . "<br>"; // 13
echo "Odejmowanie: " . ($a - $b) . "<br>"; // 7
echo "Mnożenie: " . ($a * $b) . "<br>"; // 30
echo "Dzielenie: " . ($a / $b) . "<br>"; // 3.333...
echo "Modulo: " . ($a % $b) . "<br>"; // 1
echo "Potęgowanie: " . ($a ** $b) . "<br>"; // 1000 (10 do potęgi 3)
// Dzielenie przez zero
// $wynikDzieleniaPrzezZero = 10 / 0; // Spowoduje błąd Warning: Division by zero (PHP 7) lub Fatal error: Uncaught DivisionByZeroError (PHP 8+)
// echo $wynikDzieleniaPrzezZero;
// Modulo z liczbami ujemnymi
echo "-10 % 3 = " . (-10 % 3) . "<br>"; // -1
echo "10 % -3 = " . (10 % -3) . "<br>"; // 1
?>
Warto zauważyć, że operator +
może być również używany do łączenia tablic (unia tablic), ale jego działanie jest inne niż konkatenacja ciągów znaków (do tego służy kropka .
). Jeśli spróbujesz użyć operatorów arytmetycznych na nie-numerycznych ciągach znaków, PHP spróbuje je przekonwertować na liczby, co może prowadzić do nieoczekiwanych wyników lub ostrzeżeń (jak widzieliśmy w lekcji o typach danych).
Operatory Przypisania
Podstawowym operatorem przypisania jest =
, który przypisuje wartość prawego operandu do lewego operandu (np. zmiennej).
<?php
$wiek = 30;
$nazwisko = "Kowalski";
?>
PHP oferuje również skrócone operatory przypisania, które łączą operację arytmetyczną lub bitową z przypisaniem. Są one bardzo wygodne do modyfikowania wartości zmiennej w miejscu.
Operator | Przykład | Równoważne z | Opis |
---|---|---|---|
+= |
$a += $b |
$a = $a + $b |
Dodaj i przypisz. |
-= |
$a -= $b |
$a = $a - $b |
Odejmij i przypisz. |
*= |
$a *= $b |
$a = $a * $b |
Pomnóż i przypisz. |
/= |
$a /= $b |
$a = $a / $b |
Podziel i przypisz. |
%= |
$a %= $b |
$a = $a % $b |
Modulo i przypisz. |
**= |
$a **= $b |
$a = $a ** $b |
Spotęguj i przypisz (od PHP 5.6). |
.= |
$str .= " tekst" |
$str = $str . " tekst" |
Połącz ciągi znaków (konkatenacja) i przypisz. |
??= |
$a ??= $b |
$a = $a ?? $b (lub if (!isset($a)) { $a = $b; } ) |
Operator przypisania koalescencyjnego (Null Coalesce Assignment Operator, od PHP 7.4). Przypisuje wartość prawego operandu do lewego tylko wtedy, gdy lewy operand jest NULL . |
Istnieją również skrócone operatory przypisania dla operatorów bitowych (&=
, |=
, ^=
, <<=
, >>=
), które omówimy później.
<?php
$licznik = 10;
$licznik += 5; // $licznik teraz wynosi 15
echo "Licznik: $licznik <br>";
$tekst = "Witaj, ";
$tekst .= "świecie!"; // $tekst teraz wynosi "Witaj, świecie!"
echo "Tekst: $tekst <br>";
$domyslnaWartosc = "Brak danych";
// $ustawionaWartosc = "Jakaś wartość"; // Odkomentuj, aby zobaczyć różnicę
$finalnaWartosc = $ustawionaWartosc ?? $domyslnaWartosc; // Operator koalescencyjny
echo "Finalna wartość (??): $finalnaWartosc <br>";
// Operator przypisania koalescencyjnego (??=)
$konfiguracja["port"] = $konfiguracja["port"] ?? 8080; // Starszy sposób
// lub z ??=
$konfiguracja["host"] ??= "localhost";
var_dump($konfiguracja);
?>
Operatory Porównania
Operatory porównania pozwalają na porównywanie dwóch wartości. Wynikiem operacji porównania jest zawsze wartość logiczna (bool
): true
lub false
. Są one niezwykle ważne w instrukcjach warunkowych i pętlach.
Operator | Nazwa | Przykład | Opis |
---|---|---|---|
== |
Równy (luźne porównanie) | $a == $b |
Zwraca true , jeśli $a jest równe $b po konwersji typów (type juggling). Np. 5 == "5" jest true . |
=== |
Identyczny (ścisłe porównanie) | $a === $b |
Zwraca true , jeśli $a jest równe $b ORAZ są tego samego typu. Np. 5 === "5" jest false . Zalecane jest używanie tego operatora, gdy tylko to możliwe, aby uniknąć niejednoznaczności. |
!= lub <> |
Różny (luźne porównanie) | $a != $b |
Zwraca true , jeśli $a nie jest równe $b po konwersji typów. |
!== |
Nieidentyczny (ścisłe porównanie) | $a !== $b |
Zwraca true , jeśli $a nie jest równe $b LUB nie są tego samego typu. |
< |
Mniejszy niż | $a < $b |
Zwraca true , jeśli $a jest mniejsze niż $b . |
> |
Większy niż | $a > $b |
Zwraca true , jeśli $a jest większe niż $b . |
<= |
Mniejszy lub równy | $a <= $b |
Zwraca true , jeśli $a jest mniejsze lub równe $b . |
>= |
Większy lub równy | $a >= $b |
Zwraca true , jeśli $a jest większe lub równe $b . |
<=> |
Operator statku kosmicznego (Spaceship Operator, od PHP 7) | $a <=> $b |
Zwraca int : -1 jeśli $a < $b , 0 jeśli $a == $b , 1 jeśli $a > $b . Przydatny do sortowania. |
<?php
$x = 5;
$y = "5";
$z = 10;
var_dump($x == $y); // bool(true) - luźne porównanie, "5" jest konwertowane na liczbę 5
var_dump($x === $y); // bool(false) - ścisłe porównanie, typy są różne (int vs string)
var_dump($x != $z); // bool(true)
var_dump($x !== $y); // bool(true)
var_dump($x < $z); // bool(true)
var_dump($x >= $z); // bool(false)
$a = 5;
$b = 10;
$c = 5;
echo "$a <=> $b: " . ($a <=> $b) . "<br>"; // -1
echo "$a <=> $c: " . ($a <=> $c) . "<br>"; // 0
echo "$b <=> $a: " . ($b <=> $a) . "<br>"; // 1
?>
Zawsze preferuj ścisłe porównanie (===
i !==
), aby uniknąć subtelnych błędów wynikających z automatycznej konwersji typów, chyba że świadomie potrzebujesz luźnego porównania.
Operatory Inkrementacji / Dekrementacji
Te operatory służą do zwiększania (inkrementacja) lub zmniejszania (dekrementacja) wartości zmiennej numerycznej o jeden. Mogą być używane jako pre-inkrementacja/dekrementacja (przed zmienną) lub post-inkrementacja/dekrementacja (po zmiennej).
Operator | Nazwa | Przykład | Opis |
---|---|---|---|
++$a |
Pre-inkrementacja | $b = ++$a; |
Zwiększa $a o jeden, a następnie zwraca nową wartość $a . |
$a++ |
Post-inkrementacja | $b = $a++; |
Zwraca oryginalną wartość $a , a następnie zwiększa $a o jeden. |
--$a |
Pre-dekrementacja | $b = --$a; |
Zmniejsza $a o jeden, a następnie zwraca nową wartość $a . |
$a-- |
Post-dekrementacja | $b = $a--; |
Zwraca oryginalną wartość $a , a następnie zmniejsza $a o jeden. |
<?php
$i = 5;
echo "Początkowe i: $i <br>"; // 5
$j = ++$i; // Pre-inkrementacja: $i staje się 6, $j dostaje 6
echo "Po ++i: i=$i, j=$j <br>"; // i=6, j=6
$k = $i++; // Post-inkrementacja: $k dostaje aktualne $i (czyli 6), $i staje się 7
echo "Po i++: i=$i, k=$k <br>"; // i=7, k=6
$m = 10;
echo "Początkowe m: $m <br>"; // 10
$n = --$m; // Pre-dekrementacja: $m staje się 9, $n dostaje 9
echo "Po --m: m=$m, n=$n <br>"; // m=9, n=9
$p = $m--; // Post-dekrementacja: $p dostaje aktualne $m (czyli 9), $m staje się 8
echo "Po m--: m=$m, p=$p <br>"; // m=8, p=9
// Inkrementacja/dekrementacja działa również na ciągach znaków, ale w specyficzny sposób (np. "Z"++ da "AA")
// oraz na wartościach NULL (NULL++ da 1).
$litera = "A";
$litera++;
echo "Litera po inkrementacji: $litera <br>"; // B
$nullVal = null;
$nullVal++;
echo "NULL po inkrementacji: $nullVal, typ: " . gettype($nullVal) . "<br>"; // 1, typ: integer
?>
Operatory te są często używane w pętlach do kontrolowania liczby iteracji.
Operatory Logiczne
Operatory logiczne służą do łączenia wyrażeń warunkowych. Wynikiem operacji logicznej jest zawsze wartość bool
(true
lub false
).
Operator | Nazwa | Przykład | Opis |
---|---|---|---|
and lub && |
Koniunkcja (AND) | $a and $b $a && $b |
Zwraca true , jeśli oba operandy ($a i $b ) są true . W przeciwnym razie zwraca false . Różnią się priorytetem (operator && ma wyższy priorytet niż and ). |
or lub || |
Alternatywa (OR) | $a or $b $a || $b |
Zwraca true , jeśli przynajmniej jeden z operandów ($a lub $b ) jest true . Zwraca false tylko wtedy, gdy oba są false . Różnią się priorytetem (|| ma wyższy priorytet niż or ). |
xor |
Alternatywa Wyłączająca (XOR) | $a xor $b |
Zwraca true , jeśli dokładnie jeden z operandów jest true (ale nie oba). |
! |
Negacja (NOT) | !$a |
Zwraca true , jeśli $a jest false , i false , jeśli $a jest true . (Operator unarny). |
Kolejność wykonywania (Short-circuit evaluation): Operatory &&
i ||
wykonują tzw. "short-circuit evaluation". Oznacza to, że jeśli wynik całego wyrażenia można określić na podstawie wartości pierwszego operandu, drugi operand nie jest w ogóle obliczany.
- Dla
$a && $b
: jeśli$a
jestfalse
, całe wyrażenie jestfalse
, więc$b
nie jest obliczane. - Dla
$a || $b
: jeśli$a
jesttrue
, całe wyrażenie jesttrue
, więc$b
nie jest obliczane.
Jest to ważne, gdy drugi operand jest np. wywołaniem funkcji, która ma efekty uboczne.
<?php
$wiek = 25;
$maPrawoJazdy = true;
$jestTrzezwy = true;
// && (AND)
if ($wiek >= 18 && $maPrawoJazdy && $jestTrzezwy) {
echo "Możesz prowadzić samochód.<br>";
} else {
echo "Nie możesz prowadzić samochodu.<br>";
}
$jestAdminem = false;
$jestModerator = true;
// || (OR)
if ($jestAdminem || $jestModerator) {
echo "Masz uprawnienia do zarządzania treścią.<br>";
} else {
echo "Nie masz uprawnień do zarządzania treścią.<br>";
}
// ! (NOT)
$swiatloWlaczone = false;
if (!$swiatloWlaczone) {
echo "Światło jest wyłączone.<br>";
}
// xor (XOR)
$a = true;
$b = false;
$c = true;
var_dump($a xor $b); // bool(true) - jeden jest true
var_dump($a xor $c); // bool(false) - oba są true
// Różnica w priorytetach między `and` a `&&`
$wynik1 = true && false; // $wynik1 = (true && false) => false
$wynik2 = true and false; // $wynik2 = true; (bo = ma wyższy priorytet niż `and`)
// Aby uzyskać zamierzony efekt: $wynik2 = (true and false); => false
var_dump($wynik1, $wynik2);
// Zaleca się używanie && i || zamiast `and` i `or` dla uniknięcia problemów z priorytetami,
// lub stosowanie nawiasów dla jasności.
?>
Operatory Bitowe
Operatory bitowe działają na poszczególnych bitach liczb całkowitych. Są one rzadziej używane w typowym programowaniu webowym, ale mogą być przydatne w niektórych specyficznych zastosowaniach (np. praca z flagami, maskami bitowymi, niskopoziomowe operacje).
Operator | Nazwa | Przykład | Opis |
---|---|---|---|
& |
Bitowe AND (Koniunkcja) | $a & $b |
Ustawia bity w wyniku, które są ustawione w obu operandach. |
| |
Bitowe OR (Alternatywa) | $a | $b |
Ustawia bity w wyniku, które są ustawione w przynajmniej jednym z operandów. |
^ |
Bitowe XOR (Alternatywa Wyłączająca) | $a ^ $b |
Ustawia bity w wyniku, które są ustawione w jednym z operandów, ale nie w obu. |
~ |
Bitowe NOT (Negacja) | ~$a |
Odwraca wszystkie bity w operandzie. (Operator unarny). |
<< |
Przesunięcie Bitowe w Lewo (Left Shift) | $a << $b |
Przesuwa bity $a o $b pozycji w lewo (każde przesunięcie o 1 w lewo jest równoważne mnożeniu przez 2). |
>> |
Przesunięcie Bitowe w Prawo (Right Shift) | $a >> $b |
Przesuwa bity $a o $b pozycji w prawo (każde przesunięcie o 1 w prawo jest równoważne dzieleniu przez 2, z obcięciem części ułamkowej). |
<?php
$val1 = 6; // Binarnie: 0110
$val2 = 3; // Binarnie: 0011
// 0110 ($val1)
// &
// 0011 ($val2)
// ----
// 0010 (wynik = 2)
echo "$val1 & $val2 = " . ($val1 & $val2) . "<br>"; // 2
// 0110 ($val1)
// |
// 0011 ($val2)
// ----
// 0111 (wynik = 7)
echo "$val1 | $val2 = " . ($val1 | $val2) . "<br>"; // 7
// 0110 ($val1)
// ^
// 0011 ($val2)
// ----
// 0101 (wynik = 5)
echo "$val1 ^ $val2 = " . ($val1 ^ $val2) . "<br>"; // 5
// ~0110 (~$val1) - zależy od rozmiaru int, np. dla 8 bitów z uzupełnieniem do dwóch:
// 0110 => bity odwrócone 1001. Jeśli interpretowane jako liczba ze znakiem (uzupełnienie do 2),
// to 1001 jest reprezentacją -7 (dla 4 bitów). Dla typowego int 32/64 bitowego wynik będzie inny.
// W PHP ~x jest równoważne -(x+1) dla liczb całkowitych.
echo "~$val1 = " . (~$val1) . "<br>"; // -7
// 0110 ($val1) przesunięte o 1 w lewo: 1100 (wynik = 12)
echo "$val1 << 1 = " . ($val1 << 1) . "<br>"; // 12
// 0110 ($val1) przesunięte o 1 w prawo: 0011 (wynik = 3)
echo "$val1 >> 1 = " . ($val1 >> 1) . "<br>"; // 3
?>
Operator Kontroli Błędów (Error Control Operator)
Operator @
(małpa), gdy jest umieszczony przed wyrażeniem PHP (np. wywołaniem funkcji), powoduje, że wszelkie komunikaty o błędach (Notices, Warnings, Errors) wygenerowane przez to wyrażenie zostaną zignorowane. Interpreter PHP nie wyświetli ich ani nie zaloguje.
<?php
// Przykład: próba otwarcia nieistniejącego pliku
$uchwyt1 = fopen("nieistniejacy_plik.txt", "r"); // Wygeneruje Warning
if ($uchwyt1 === false) {
echo "Nie udało się otworzyć pliku (bez @).<br>";
}
// Ta sama operacja z operatorem @
$uchwyt2 = @fopen("nieistniejacy_plik.txt", "r"); // Warning zostanie stłumiony
if ($uchwyt2 === false) {
echo "Nie udało się otworzyć pliku (z @), błąd stłumiony.<br>";
}
// Użycie @ z niezdefiniowaną zmienną
// echo $niezdefiniowana; // Wygeneruje Notice: Undefined variable
// echo @$niezdefiniowana; // Notice zostanie stłumiony (wyświetli pusty ciąg)
?>
Uwaga: Używanie operatora @
jest generalnie złą praktyką i powinno być unikane. Tłumienie błędów utrudnia debugowanie i może maskować poważne problemy w aplikacji. Zamiast tego należy stosować odpowiednie mechanizmy obsługi błędów, takie jak sprawdzanie wartości zwracanych przez funkcje, używanie bloków try-catch
do obsługi wyjątków (o czym w późniejszej lekcji), oraz konfigurowanie odpowiedniego poziomu raportowania błędów na serwerze deweloperskim.
Są bardzo rzadkie przypadki, gdy @
może być użyteczne (np. gdy funkcja nie oferuje innego sposobu na sprawdzenie błędu niż wygenerowanie ostrzeżenia, a my chcemy ten błąd obsłużyć w specyficzny sposób), ale należy podchodzić do tego z dużą ostrożnością.
Operator Wykonania (Execution Operator)
PHP obsługuje jeden operator wykonania: grawisy (backticks) ``
. PHP spróbuje wykonać zawartość grawisów jako polecenie systemowe (shell command), a wynik tego polecenia zostanie zwrócony jako ciąg znaków. Działa to podobnie do funkcji shell_exec()
.
<?php
// Przykład (może nie działać na wszystkich systemach lub jeśli PHP nie ma uprawnień)
// $listaPlikow = `ls -la`; // Na systemach Unix-like
// $wersjaSystemu = `ver`; // Na systemach Windows
// echo "<pre>$listaPlikow</pre>";
// Lepszym i bardziej kontrolowanym sposobem jest użycie funkcji takich jak shell_exec(), exec(), system(), passthru()
$output = shell_exec("echo Witaj z powłoki!");
echo $output;
?>
Uwaga dotycząca bezpieczeństwa: Używanie operatora wykonania lub funkcji wykonujących polecenia systemowe jest bardzo ryzykowne, jeśli jakiekolwiek dane pochodzące od użytkownika są włączane do tych poleceń bez odpowiedniego oczyszczenia i walidacji. Może to prowadzić do luk bezpieczeństwa typu "command injection". Jeśli to możliwe, unikaj wykonywania poleceń systemowych w ten sposób lub rób to z najwyższą ostrożnością.
Operator Ciągu Znaków (String Operator)
PHP ma jeden operator przeznaczony specjalnie do pracy z ciągami znaków:
.
(Kropka - Konkatenacja): Służy do łączenia (konkatenacji) dwóch ciągów znaków.
<?php
$imie = "Anna";
$nazwisko = "Nowak";
$pelneImie = $imie . " " . $nazwisko; // Łączy imię, spację i nazwisko
echo $pelneImie; // Wyświetli "Anna Nowak"
$powitanie = "Witaj, ";
$powitanie .= $imie . "!"; // Użycie skróconego operatora .= (powitanie = powitanie . $imie . "!")
echo "<br>" . $powitanie; // Wyświetli "Witaj, Anna!"
?>
Operatory Tablicowe
PHP dostarcza specjalne operatory do pracy z tablicami:
Operator | Nazwa | Przykład | Opis |
---|---|---|---|
+ |
Unia | $a + $b |
Łączy tablicę $a z tablicą $b . Jeśli obie tablice mają elementy o tych samych kluczach, używane są elementy z tablicy po lewej stronie operatora ($a ), a elementy z $b o tych samych kluczach są ignorowane. Klucze numeryczne nie są переиндексировываются. |
== |
Równość (luźna) | $a == $b |
Zwraca true , jeśli tablica $a ma te same pary klucz-wartość co tablica $b , niezależnie od kolejności i typów wartości (po konwersji). |
=== |
Identyczność (ścisła) | $a === $b |
Zwraca true , jeśli tablica $a ma te same pary klucz-wartość co tablica $b , w tej samej kolejności i wartości są tego samego typu. |
!= lub <> |
Nierówność (luźna) | $a != $b |
Przeciwieństwo == . |
!== |
Nieidentyczność (ścisła) | $a !== $b |
Przeciwieństwo === . |
<?php
$tab1 = ["a" => "czerwony", "b" => "zielony"];
$tab2 = ["b" => "niebieski", "c" => "żółty"];
$tab3 = [0 => "jabłko", 1 => "banan"];
$tab4 = [1 => "banan", 0 => "jabłko"]; // Ta sama zawartość, inna kolejność kluczy numerycznych
$unia = $tab1 + $tab2;
print_r($unia);
// Wynik: Array ( [a] => czerwony [b] => zielony [c] => żółty )
// Klucz "b" z $tab1 został zachowany.
echo "<br>";
$arr1 = [1, 2, 3];
$arr2 = ["1", "2", "3"];
$arr3 = [1, 2, 3];
$arr4 = [3, 2, 1]; // Inna kolejność wartości dla kluczy numerycznych
var_dump($arr1 == $arr2); // bool(true) - luźne porównanie wartości
var_dump($arr1 === $arr2); // bool(false) - typy wartości są różne
var_dump($arr1 === $arr3); // bool(true) - identyczne
var_dump($arr1 == $arr4); // bool(false) - kolejność ma znaczenie dla kluczy numerycznych
$assoc1 = ["a" => 1, "b" => 2];
$assoc2 = ["b" => 2, "a" => 1]; // Ta sama zawartość, inna kolejność kluczy asocjacyjnych
$assoc3 = ["a" => "1", "b" => "2"];
var_dump($assoc1 == $assoc2); // bool(true) - kolejność kluczy asocjacyjnych nie ma znaczenia dla ==
var_dump($assoc1 === $assoc2); // bool(false) - kolejność kluczy ma znaczenie dla ===
var_dump($assoc1 == $assoc3); // bool(true)
var_dump($assoc1 === $assoc3); // bool(false)
?>
Szczegółowe omówienie tablic i operacji na nich znajdzie się w dedykowanej lekcji.
Operator Typu (Type Operator)
PHP posiada jeden operator typu:
instanceof
: Służy do sprawdzania, czy obiekt jest instancją określonej klasy, instancją klasy dziedziczącej po tej klasie, lub czy implementuje określony interfejs.
<?php
class MojaKlasa {}
class InnaKlasa extends MojaKlasa {}
interface MojInterfejs {}
class KlasaImplementujaca implements MojInterfejs {}
$obj1 = new MojaKlasa();
$obj2 = new InnaKlasa();
$obj3 = new KlasaImplementujaca();
$obj4 = new stdClass(); // Generyczny pusty obiekt
var_dump($obj1 instanceof MojaKlasa); // bool(true)
var_dump($obj2 instanceof MojaKlasa); // bool(true) - InnaKlasa dziedziczy po MojaKlasa
var_dump($obj2 instanceof InnaKlasa); // bool(true)
var_dump($obj1 instanceof InnaKlasa); // bool(false)
var_dump($obj3 instanceof MojInterfejs); // bool(true)
var_dump($obj4 instanceof MojaKlasa); // bool(false)
// Można też używać z nazwami klas jako ciągami znaków (od PHP 5.1.0)
$nazwaKlasy = "MojaKlasa";
var_dump($obj1 instanceof $nazwaKlasy); // bool(true)
?>
Ten operator jest fundamentalny w programowaniu obiektowym, o którym będziemy mówić w drugiej części kursu.
Operator Koalescencji (Null Coalesce Operator)
Wprowadzony w PHP 7, operator ??
(podwójny znak zapytania) jest bardzo użytecznym skrótem do sprawdzania, czy zmienna istnieje (jest ustawiona) i nie jest NULL
. Jeśli tak, zwraca jej wartość; w przeciwnym razie zwraca wartość domyślną (prawy operand).
$wynik = $zmienna_do_sprawdzenia ?? $wartosc_domyslna;
Jest to równoważne z:
$wynik = isset($zmienna_do_sprawdzenia) ? $zmienna_do_sprawdzenia : $wartosc_domyslna;
<?php
// Przykład 1: Zmienna istnieje i nie jest NULL
$uzytkownik = "Jan";
$nazwaDoWyswietlenia = $uzytkownik ?? "Gość";
echo "Nazwa do wyświetlenia: $nazwaDoWyswietlenia <br>"; // Jan
// Przykład 2: Zmienna nie istnieje (lub jest NULL)
// unset($nieistniejacyUzytkownik); // Upewniamy się, że nie istnieje
$nazwaDoWyswietlenia2 = $nieistniejacyUzytkownik ?? "Gość";
echo "Nazwa do wyświetlenia 2: $nazwaDoWyswietlenia2 <br>"; // Gość
// Przykład 3: Zmienna jest ustawiona na NULL
$adres = NULL;
$wyswietlAdres = $adres ?? "Brak adresu";
echo "Adres: $wyswietlAdres <br>"; // Brak adresu
// Można łączyć operatory ??
$domyslnyKolor = "czarny";
$kolorUzytkownika = null; // np. z bazy danych
$kolorProduktu = "czerwony";
$finalnyKolor = $kolorUzytkownika ?? $kolorProduktu ?? $domyslnyKolor;
echo "Finalny kolor: $finalnyKolor <br>"; // czerwony
?>
Jak widzieliśmy wcześniej, od PHP 7.4 istnieje również operator przypisania koalescencyjnego ??=
.
Priorytet i Łączność Operatorów
Gdy w jednym wyrażeniu występuje wiele operatorów, PHP musi zdecydować, w jakiej kolejności je wykonać. Określa to priorytet operatorów. Na przykład operator mnożenia (*
) ma wyższy priorytet niż operator dodawania (+
), więc w wyrażeniu 2 + 3 * 4
najpierw zostanie wykonane mnożenie (3 * 4 = 12
), a następnie dodawanie (2 + 12 = 14
).
Łączność operatorów określa, jak operatory o tym samym priorytecie są grupowane: od lewej do prawej (łączność lewostronna) lub od prawej do lewej (łączność prawostronna).
Pełna tabela priorytetów i łączności operatorów w PHP jest dostępna w oficjalnej dokumentacji (php.net/manual/pl/language.operators.precedence.php). Nie trzeba jej uczyć się na pamięć, ale warto znać ogólne zasady (np. arytmetyczne przed porównaniem, porównanie przed logicznymi).
Aby uniknąć niejednoznaczności i zapewnić czytelność kodu, zawsze zaleca się używanie nawiasów ()
do jawnego określania kolejności wykonywania operacji, nawet jeśli priorytet jest oczywisty.
<?php
$wynik1 = 2 + 3 * 4; // Wynik: 14 (mnożenie pierwsze)
$wynik2 = (2 + 3) * 4; // Wynik: 20 (dodawanie pierwsze dzięki nawiasom)
echo "Wynik1: $wynik1, Wynik2: $wynik2 <br>";
$a = 5;
$b = 3;
$c = 2;
// Łączność lewostronna dla -, +
$res = $a - $b + $c; // (5 - 3) + 2 = 2 + 2 = 4
echo "$a - $b + $c = $res <br>";
// Łączność prawostronna dla operatora trójargumentowego i przypisań
$x = true ? 1 : false ? 2 : 3; // Interpretowane jako: true ? 1 : (false ? 2 : 3) => 1
$y = ($x = 10) + 5; // Najpierw przypisanie $x = 10, potem $y = 10 + 5 => 15
var_dump($x, $y);
?>
Podsumowanie Lekcji
W tej lekcji dogłębnie omówiliśmy szeroki wachlarz operatorów dostępnych w PHP. Poznaliśmy operatory arytmetyczne, przypisania (w tym skrócone i koalescencyjne), porównania (luźne i ścisłe), inkrementacji/dekrementacji, logiczne (z uwzględnieniem short-circuit evaluation), bitowe, kontroli błędów, wykonania, ciągu znaków, tablicowe, typu oraz koalescencji NULL. Zrozumieliśmy również znaczenie priorytetu i łączności operatorów oraz jak ważne jest stosowanie nawiasów dla czytelności i jednoznaczności kodu.
Operatory są narzędziami, które pozwalają na manipulowanie danymi i podejmowanie decyzji w programach. Ich efektywne wykorzystanie jest niezbędne do tworzenia złożonej logiki. W następnej lekcji zobaczymy, jak operatory porównania i logiczne współdziałają z instrukcjami warunkowymi (if
, else
, elseif
), aby umożliwić programom podejmowanie decyzji w zależności od spełnienia określonych warunków.
Zadanie praktyczne
Napisz skrypt PHP, który:
- Zadeklaruj dwie zmienne numeryczne, np.
$liczba1 = 15;
i$liczba2 = 4;
. - Wykonaj i wyświetl wyniki wszystkich podstawowych operacji arytmetycznych (dodawanie, odejmowanie, mnożenie, dzielenie, modulo, potęgowanie) na tych zmiennych.
- Zadeklaruj zmienną
$tekstPoczatkowy = "PHP jest ";
. Użyj operatora konkatenacji i przypisania (.=
), aby dodać do niej słowo "super!". Wyświetl finalny tekst. - Zadeklaruj dwie zmienne, jedną typu
int
(np.$a = 100;
) i drugą typustring
przechowującą tę samą liczbę (np.$b = "100";
). Sprawdź i wyświetl wyniki porównania ich za pomocą operatorów==
oraz===
. Wyjaśnij w komentarzu, dlaczego wyniki są różne (lub takie same). - Zadeklaruj zmienną
$wiekUzytkownika
. Użyj operatora koalescencji NULL (??
), aby przypisać do zmiennej$status
wartość "Dorosły", jeśli$wiekUzytkownika
jest większy lub równy 18, lub "Niepełnoletni" w przeciwnym razie. Jeśli$wiekUzytkownika
nie jest ustawiona,$status
powinien przyjąć wartość "Wiek nieznany". (Wskazówka: możesz potrzebować połączyć??
z operatorem trójargumentowym lub instrukcją if).
Pokaż przykładowe rozwiązanie
<?php
// 1. Zmienne numeryczne
$liczba1 = 15;
$liczba2 = 4;
echo "<h3>Operacje arytmetyczne dla $liczba1 i $liczba2:</h3>";
echo "Dodawanie ($liczba1 + $liczba2): " . ($liczba1 + $liczba2) . "<br>";
echo "Odejmowanie ($liczba1 - $liczba2): " . ($liczba1 - $liczba2) . "<br>";
echo "Mnożenie ($liczba1 * $liczba2): " . ($liczba1 * $liczba2) . "<br>";
echo "Dzielenie ($liczba1 / $liczba2): " . ($liczba1 / $liczba2) . "<br>";
echo "Modulo ($liczba1 % $liczba2): " . ($liczba1 % $liczba2) . "<br>";
echo "Potęgowanie ($liczba1 ** $liczba2): " . ($liczba1 ** $liczba2) . "<br>";
// 2. Konkatenacja i przypisanie
$tekstPoczatkowy = "PHP jest ";
$tekstPoczatkowy .= "super!";
echo "<h3>Konkatenacja:</h3>";
echo $tekstPoczatkowy . "<br>";
// 3. Porównanie == vs ===
$a = 100; // int
$b = "100"; // string
echo "<h3>Porównanie == vs ===:</h3>";
$wynikLuźny = ($a == $b);
$wynikScisly = ($a === $b);
echo "\$a == \$b : "; var_dump($wynikLuźny); // bool(true)
echo "<br>";
echo "\$a === \$b : "; var_dump($wynikScisly); // bool(false)
echo "<br>";
// Wyjaśnienie: Operator == (luźny) konwertuje typy przed porównaniem, więc string \"100\" jest traktowany jak liczba 100.
// Operator === (ścisły) sprawdza zarówno wartość, jak i typ. Ponieważ \$a jest int, a \$b jest string, wynik jest false.
// 4. Operator koalescencji i status wieku
// $wiekUzytkownika = 20; // Odkomentuj i testuj różne wartości lub brak definicji
// $wiekUzytkownika = 15;
// $wiekUzytkownika = null;
echo "<h3>Status wieku:</h3>";
$status = ($wiekUzytkownika ?? "Wiek nieznany");
if ($status !== "Wiek nieznany") { // Jeśli wiek jest znany, sprawdź czy dorosły
$status = ($wiekUzytkownika >= 18) ? "Dorosły" : "Niepełnoletni";
}
echo "Status użytkownika: $status <br>";
// Alternatywne, bardziej zwięzłe rozwiązanie dla punktu 4, jeśli $wiekUzytkownika może być nieustawiony:
$status2 = isset($wiekUzytkownika) ? ($wiekUzytkownika >= 18 ? "Dorosły" : "Niepełnoletni") : "Wiek nieznany";
echo "Status użytkownika (alternatywnie): $status2 <br>";
?>
Zadanie do samodzielnego wykonania
Napisz skrypt, który symuluje prosty system rabatowy. Zadeklaruj zmienną $cenaProduktu
oraz zmienną logiczną $posiadaKarteKlienta
. Jeśli klient posiada kartę klienta, przyznaj mu 10% rabatu. Jeśli cena produktu po ewentualnym rabacie jest większa niż 100 zł, przyznaj dodatkowy rabat 5% od aktualnej ceny. Wyświetl cenę początkową, informację o przyznanych rabatach (jeśli były) oraz cenę końcową. Użyj operatorów arytmetycznych, przypisania, porównania i logicznych.
FAQ - Operatory w PHP
Jaka jest różnica między =
, ==
, a ===
?
=
to operator przypisania (przypisuje wartość). ==
to operator porównania równości (luźny, konwertuje typy). ===
to operator porównania identyczności (ścisły, sprawdza wartość i typ). Zawsze staraj się używać ===
do porównań, aby uniknąć niejednoznaczności.
Czy mogę używać operatorów inkrementacji/dekrementacji na ciągach znaków?
Tak, PHP pozwala na inkrementację ciągów znaków w specyficzny sposób. Na przykład, "Z"++
da "AA"
, a "a9"++
da "b0"
. Działa to na zasadzie "przenoszenia" jak w systemach liczbowych, ale tylko dla liter i cyfr. Nie jest to jednak często używana funkcjonalność.
Kiedy używać and
/or
zamiast &&
/||
?
Generalnie zaleca się używanie &&
i ||
, ponieważ mają one wyższy i bardziej intuicyjny priorytet w większości sytuacji, zwłaszcza w instrukcjach if
. Operatory and
i or
mają niższy priorytet, co może być przydatne w niektórych specyficznych konstrukcjach, np. $plik = fopen(...) or die("Błąd otwarcia pliku!");
, ale często prowadzi do błędów, jeśli nie użyje się nawiasów przy przypisaniach.
Co to jest operator trójargumentowy (ternary operator)?
Operator trójargumentowy ?:
to skrócona forma instrukcji if-else. Ma postać (warunek) ? wartosc_jesli_prawda : wartosc_jesli_falsz;
. Jeśli warunek jest prawdziwy, całe wyrażenie przyjmuje wartosc_jesli_prawda
, w przeciwnym razie wartosc_jesli_falsz
.
Czy operator @
wpływa na wydajność?
Tak, użycie operatora kontroli błędów @
może nieznacznie obniżyć wydajność, ponieważ PHP musi wykonać dodatkową pracę, aby stłumić błędy. Jednak głównym powodem, dla którego należy go unikać, jest utrudnianie debugowania, a nie kwestie wydajnościowe w typowych zastosowaniach.
Jak działa operator +
dla tablic? Czy łączy elementy jak array_merge()
?
Operator +
dla tablic (unia) działa inaczej niż array_merge()
. Operator +
dodaje elementy z prawej tablicy do lewej, ale jeśli klucze się powtarzają, elementy z lewej tablicy są zachowywane, a te z prawej ignorowane. array_merge()
nadpisuje wartości dla kluczy stringowych i dodaje na końcu dla kluczy numerycznych (reindeksując je, jeśli są tylko numeryczne).
Czy mogę tworzyć własne operatory w PHP?
Nie, PHP nie pozwala na definiowanie przez użytkownika własnych operatorów ani na przeciążanie istniejących operatorów w taki sposób, jak to jest możliwe w niektórych innych językach (np. C++). Można jednak emulować pewne zachowania za pomocą metod magicznych w klasach (np. dla operacji na obiektach).