Jeśli kiedykolwiek programowałeś w PHP, na pewno spotkałeś się z sytuacją, w której wynik porównania zaskoczył Cię. Może to było coś w stylu:
var_dump("0" == false); // true?!
I wtedy zaczyna się myślenie: „Chwileczkę… przecież ‘0’ to string, a false to wartość logiczna. Jak to możliwe, że PHP mówi, że są równe?”.
Właśnie o tym będzie ten artykuł. Dowiesz się, jak PHP porównuje wartości, które nie są liczbami, dlaczego czasem wyniki są nieintuicyjne i jak unikać błędów. Będzie prosto, po ludzku i z konkretnymi przykładami.
Czym właściwie jest „porównanie” w PHP?
W PHP porównania możesz wykonywać na różne sposoby, ale najczęściej spotkasz dwa operatory:
==→ porównanie z konwersją typów (tzw. loose comparison),===→ porównanie bez konwersji typów (tzw. strict comparison).
Jeśli PHP widzi ==, to często „dopasowuje” typy, żeby je dało się porównać.
To znaczy, że jeśli porównasz string z liczbą, PHP spróbuje przekonwertować string na liczbę.
Ale kiedy porównujesz np. true i "hello", sprawa robi się ciekawa.
PHP ma swoje wewnętrzne zasady, które decydują, jak dokonać takiej konwersji — i to właśnie one prowadzą do zaskoczeń.
Jak PHP konwertuje typy podczas porównań?
Zasada ogólna:
Gdy porównujesz dwa różne typy (np. string i bool), PHP konwertuje je według ustalonej hierarchii, by móc wykonać porównanie.
Przykład 1: String vs liczba
Jeśli jeden z operandów to liczba, a drugi to string, PHP próbuje zamienić string na liczbę.
var_dump("10" == 10); // true
var_dump("10 piesków" == 10); // true (!)
W drugim przykładzie PHP patrzy na początek stringa, widzi „10”, zamienia go na 10 i ignoruje resztę.
Czyli “10 piesków” → 10.
Zatem: 10 == 10 → true.
To logiczne… ale tylko do momentu, aż natrafisz na:
var_dump("pieski" == 0); // true
Dlaczego? Bo „pieski” nie da się zamienić na liczbę, więc PHP traktuje taki string jako 0.
I wychodzi 0 == 0 → true.
Porównanie z wartością logiczną (true / false)
Tu robi się jeszcze ciekawiej.
Jeśli porównujesz cokolwiek z wartością logiczną (true lub false), PHP zawsze konwertuje drugą wartość do typu bool.
Przykład 2: String vs bool
var_dump("0" == false); // true
var_dump("" == false); // true
var_dump(" " == false); // false
var_dump("PHP" == true); // true
Dlaczego "0" == false daje true?
Bo "0" jest traktowany jako fałsz.
Natomiast " " (spacja) to niepusty string, więc jest traktowany jako prawda (true).
To może prowadzić do bardzo nieoczywistych wyników w kodzie.
Porównanie stringów między sobą
Kiedy porównujesz dwa stringi za pomocą ==, PHP nie konwertuje ich (dopóki nie wykryje liczb na początku).
Czyli:
var_dump("abc" == "abc"); // true
var_dump("abc" == "ABC"); // false
Proste, prawda?
Ale jeśli w stringach występują cyfry, PHP może spróbować uznać je za liczby.
Na przykład:
var_dump("123" == "0123"); // true (!)
Dlaczego?
Bo oba stringi są konwertowane na liczby (123 i 123) zanim zostaną porównane.
Żeby uniknąć takiego zachowania, należy używać ścisłego porównania (===):
var_dump("123" === "0123"); // false
Tutaj PHP nie konwertuje wartości – porównuje je dokładnie, znak po znaku.
Typowe pułapki podczas porównywania nieliczbowych wartości
Pusty string i false
var_dump("" == false); // true
To może być bardzo zdradliwe, np. w warunkach:
$password = "";
if ($password == false) {
echo "Brak hasła!";
}
Zadziała, ale gdyby $password miało wartość "0", efekt byłby taki sam — a to już może być błąd logiczny.
null kontra puste stringi
var_dump(null == ""); // true var_dump(null === ""); // false
W pierwszym przypadku PHP uznaje, że null i pusty string to „prawie to samo” — oba są czymś „brakiem wartości”.
Ale w rzeczywistości to inne rzeczy. null to brak zmiennej lub brak wartości, a "" to po prostu pusty tekst.
Dlatego w praktyce zawsze warto używać operatora ścisłego (===).
Tablice i porównania
Z tablicami jest trochę inaczej. PHP nie konwertuje ich na liczby ani stringi.
Porównuje je element po elemencie.
var_dump([1, 2] == [1, 2]); // true var_dump([1, 2] == [2, 1]); // false
Tu kolejność ma znaczenie.
A przy ścisłym porównaniu (===) liczy się również typ kluczy.
var_dump([1 => "a"] === ["1" => "a"]); // false
Porównanie wartości nieliczbowych w praktyce – przykłady
Zobaczmy kilka rzeczywistych scenariuszy, które mogą Cię zaskoczyć.
Przykład 1 – weryfikacja formularza
Załóżmy, że użytkownik wprowadza wartość w formularzu, np. numer telefonu.
$phone = $_POST['phone']; // może być pusty string
if ($phone == false) {
echo "Proszę podać numer telefonu.";
}
Jeśli użytkownik wpisze "0", to warunek się spełni – a przecież "0" to niepusty string.
Rozwiązanie?
Użyj ścisłego porównania:
if ($phone === "" || $phone === null) {
echo "Proszę podać numer telefonu.";
}
Przykład 2 – porównanie z bazą danych
Załóżmy, że pobierasz dane z bazy i chcesz sprawdzić, czy użytkownik jest aktywny.
$status = "0"; // z bazy danych (VARCHAR)
if ($status == false) {
echo "Użytkownik nieaktywny";
}
PHP potraktuje "0" jako false, więc wszystko działa…
Ale jeśli w przyszłości kolumna zmieni się na np. "off", logika już się posypie.
Bezpieczniej porównywać ściśle:
if ($status === "0") {
echo "Użytkownik nieaktywny";
}
Prosty skrypt do testowania porównań
Jeśli chcesz zobaczyć, jak PHP naprawdę porównuje różne wartości, możesz uruchomić ten mały eksperyment:
<?php
$values = ["0", "", " ", "abc", "10abc", 0, null, false, true];
foreach ($values as $a) {
foreach ($values as $b) {
echo json_encode($a) . " == " . json_encode($b) . " → ";
var_dump($a == $b);
}
echo str_repeat("-", 40) . "\n";
}
?>
Ten skrypt wypisze całą tablicę wyników porównań.
Zdziwisz się, ile z nich zwróci true!
Najlepsze praktyki – jak bezpiecznie porównywać w PHP?
- Używaj
===zamiast==, jeśli tylko możesz.
Dzięki temu PHP nie będzie zgadywać, co miałeś na myśli. - Ręcznie konwertuj typy, jeśli naprawdę potrzebujesz porównać liczby ze stringami:
if ((int)$a === (int)$b) { ... } - Nie ufaj „prawdziwości” stringów –
"0"i""zachowują się inaczej, niż się wydaje. - Uważaj na dane z formularzy i baz danych – one są zawsze stringami, nawet jeśli wyglądają jak liczby.
- Testuj porównania w sytuacjach granicznych – zwłaszcza, jeśli logika warunkowa ma znaczenie dla bezpieczeństwa lub płatności.
Porównywanie wartości, które nie są liczbami w PHP, może być zdradliwe.
PHP automatycznie konwertuje typy w tle, co czasem prowadzi do niespodziewanych wyników.
Najważniejsze zasady, które warto zapamiętać:
==→ luźne porównanie z konwersją typów,===→ ścisłe porównanie, bez konwersji,- String
"0"tofalse, ale" "(spacja) totrue, - Pusty string i
nullsą różne, - Zawsze porównuj tablice i obiekty ściśle (
===).
Bonus: mała ściągawka
| Wartość 1 | Wartość 2 | Operator | Wynik | Dlaczego |
|---|---|---|---|---|
"0" | false | == | ✅ true | "0" traktowane jako false |
" " | false | == | ❌ false | spacja to niepusty string |
"" | false | == | ✅ true | pusty string to false |
"123abc" | 123 | == | ✅ true | string konwertowany do liczby |
"abc" | 0 | == | ✅ true | nie da się przekonwertować, więc 0 == 0 |
null | "" | == | ✅ true | PHP traktuje null jak pusty string |
null | "" | === | ❌ false | różne typy |
Porównywanie nieliczbowych wartości w PHP to temat, który na pierwszy rzut oka wydaje się prosty, ale potrafi złapać w pułapkę nawet doświadczonych programistów.
Najlepszą praktyką jest zawsze myśleć o typach danych i używać ścisłych operatorów (===, !==) wszędzie tam, gdzie to możliwe.