Operatory logiczne PHP

Operatory logiczne PHP służą do tworzenia wyrażeń logicznych. Zwracają wartość reprezentującą prawdę lub fałsz, zależnie od tego, czy został spełniony pewien warunek. W języku PHP jest 6 takich operatorów i w tym rozdziale kursu poznasz tajniki każdego z nich.

Czy wiesz na przykład, jak w PHP wyrazić, że interesują cię wszystkie liczby mniejsze lub większe od zera, ale nie samo zero? Albo, czy wiesz, jak w PHP sprawdzić, czy użytkownik sklepu internetowego spełnia wszystkie wymagania niezbędne do tego, aby otrzymać rabat?

W tym rozdziale nauczysz się pisać takie wyrażenia i wiele więcej. Ponadto między innymi poznasz odpowiedzi na następujące pytania:

  1. Jakie są operatory logiczne w PHP?
  2. Czym jest suma logiczna?
  3. Czym jest iloczyn logiczny?
  4. Czym jest negacja logiczna?
  5. Co robi && w PHP?
  6. Co to jest xor w PHP?
  7. Co wspólnego z PHP ma XIX-wieczny uczony o nazwisku George Boole?

Jakie są operatory logiczne PHP

W języku PHP jest 6 operatorów logicznych. Choć może się wydawać, że to niewiele, ten zestaw w zupełności wystarczający do napisania każdej potrzebnej konstrukcji logicznej.

Poniższa tabela zawiera zwięzłe zestawienie wszystkich operatorów logicznych PHP, a pod nią znajdziesz szczegółowe objaśnienia tego, czym są i jak działają.

Operatory logiczne PHP
OperatorNazwaPrzykładSposób działania
andAND (I, koniunkcja)$a > 5 and $a < 10Zwraca true, jeśli oba argumenty mają wartość true
orOR (LUB, alternatywa, suma logiczna)$a < 0 or $a > 10Zwraca true, jeśli przynajmniej jeden z argumentów ma wartość true
xorXOR (alternatywa rozłączna)$a < 0 xor $a > 10Zwraca true, jeśli dokładnie jeden z argumentów ma wartość true
!NOT (NIE, negacja)!$aZwraca true, jeśli wartość $a jest różna od true
&&AND (I, koniunkcja)$a > 5 && $a < 10Zwraca true, jeśli oba argumenty mają wartość true
||OR (LUB, alternatywa)$a < 0 || $a > 10Zwraca true, jeśli przynajmniej jeden z argumentów ma wartość true

Po przyjrzeniu się tej tabeli z pewnością zastanawia Cię, jaka jest różnica między operatorami and i && oraz or i ||. Różnią się one między sobą tylko kolejnością wykonywania działań, o czym za chwilę dowiesz się więcej.

Zanim jednak do tego dojdziemy, chciałbym opowiedzieć ci krótko o tym, skąd wzięły się nazwy tych operatorów oraz dlaczego typ danych, którego wartości to true i false, ma taką dziwną nazwę bool.

Wszystko przez wspomnianego na początku tego rozdziału George’a Boole’a. Z braku lepszych zajęć wymyślił on zbiór zasad, który później po rozwinięciu przez innych badaczy nazwano na jego cześć algebrą Boole’a (choć spotkałem się też z twierdzeniami, że nazwa ta wzięła się od tego, że algebra ta powstawała w strasznych bólach).

Niektórzy żartują, że algebra Boole’a to taki rodzaj algebry, który powstawał w strasznych bólach

Podstawowe zasady algebry Boole’a

Algebra Boole’a to gałąź matematyki, która jest wykorzystywana do projektowania i analizowania układów cyfrowych. To właśnie na jej fundamencie opiera się działanie między innymi procesorów komputerowych, ale po kolei.

Algebra Boole’a posługuje się trzema podstawowymi działaniami logicznymi i dwiema wartościami logicznymi. Trzy podstawowe działania to koniunkcja, alternatywa i negacja.

W różnych kontekstach można spotkać różne oznaczenia symboliczne tych działań, ale w elektronice i programowaniu najczęściej spotyka się oznaczenia AND i &, OR i || oraz NOT i ! (i różne ich odmiany, np. zapis małymi literami) odpowiednio dla koniunkcji, alternatywy i negacji.

Na przykład w języku PHP operatorem koniunkcji z algebry Boole’a jest and lub &&, operatorem alternatywy z algebry Boole’a jest or lub ||, a operatorem negacji z algebry Boole’a jest ! (w języku tym występują też operatory & i |, ale należą one do grupy operatorów bitowych PHP, które poznasz w następnym rozdziale).

Z kolei wartości logiczne w algebrze Boole’a to 1 (prawda — ang. true) i 0 (fałsz — ang. false).

Każde z działań algebry ma ściśle określone właściwości. Matematycy lubią je ilustrować za pomocą diagramów Venna, czyli kół, zazwyczaj w jakimś stopniu się pokrywających, których część wspólna obrazuje wynik danej operacji.

Ponadto działania algebry Boole’a często przedstawia się w formie tabeli prawdy (ang. truth table), czyli zwykłej tabeli, w której są wymienione wszystkie możliwe wartości dla każdej kombinacji argumentów. Jako że tych argumentów jest maksymalnie 2 (albo jeden w przypadku negacji), to liczba ich kombinacji wynosi maksymalnie 4.

Przyjrzyjmy się więc trzem podstawowym działaniom algebry Boole’a i zobaczmy, jakie mają właściwości:

Operacja Boole’a AND

Wynikiem działania boole’owskiego AND jest prawda wtedy i tylko wtedy, gdy oba argumenty są prawdziwe. Pokazuje to poniższy diagram Venna.

Diagram venna obrazujący wynik operacji koniunkcji, operator PHP and
Koniunkcja logiczna (AND)

Jak widać na tym diagramie, koniunkcja reprezentuje część wspólną dwóch zbiorów. Nazwa tego działania pochodzi od łacińskiego słowa coniunctio oznaczającego połączenie, część wspólną.

Być może łatwiej będzie ci zapamiętać znaczenie tego słowa, jeśli skojarzysz je z angielskim słowem conjunction, które znaczy to samo, co łacińskie coniunctio.

Teraz spójrz na tabelę prawdy działania koniunkcji.

Tabela prawdy działania koniunkcji (AND)
Arg1Arg2WynikKomentarz
000Żaden z argumentów nie jest prawdziwy, więc wynik jest fałszywy
010Tylko jeden z argumentów jest prawdziwy, więc wynik jest fałszywy
100Tylko jeden z argumentów jest prawdziwy, więc wynik jest fałszywy
111Oba argumenty są prawdziwe, więc wynik też jest prawdziwy

Operacja Boole’a OR

Wynikiem działania boole’owskiego OR jest prawda wtedy, gdy którykolwiek z argumentów jest prawdziwy. Spójrz na obrazujący to diagram Venna.

Diagram venna obrazujący wynik operacji sumy symetrycznej, operator PHP or
Suma logiczna (OR)

Patrząc na ten diagram, z pewnością już wiesz, dlaczego to działanie nazywa się między innymi sumą logiczną. Logiczne LUB reprezentuje sumę logiczną dwóch zbiorów. Spójrz na tabelę prawdy tego działania.

Tabela prawdy dla działania sumy symetrycznej (OR)
Arg1Arg2WynikKomentarz
000Oba argumenty są fałszywe, więc wynik też jest fałszywy (inaczej mówiąc argumenty nie należą do żadnego ze zbiorów)
011Przynajmniej jeden argument jest prawdziwy, więc wynik też jest prawdziwy
101Przynajmniej jeden argument jest prawdziwy, więc wynik też jest prawdziwy
111Oba argumenty są prawdziwe, więc wynik też jest prawdziwy

Operacja Boole’a NOT

Wynikiem działania boole’owskiego NOT jest odwrotność jego argumentu, a więc prawda, jeśli argument jest fałszywy i fałsz, jeśli argument jest prawdziwy. Przedstawia to poniższy diagram Venna.

Diagram venna obrazujący wynik operacji negacji, operator PHP and
Negacja logiczna (NOT)

Tabela prawdy dla działania negacji jest krótsza niż dla poprzednich działań, ponieważ jest to działanie jednoargumentowe.

Tabela prawdy dla działania negacji logicznej (NOT)
ArgumentWynik
01
10

Algebra Boole’a w układach cyfrowych

Kiedy jest mowa o algebrze Boole’a, to trudno nie poszyć tematu budowy układów cyfrowych. Ponieważ nie są one tematem tego kursu, ograniczę się tylko do najbardziej podstawowych informacji, które mogą pomóc w zrozumieniu działań logicznych PHP, ale nie są niezbędne do tego zrozumienia.

Układy cyfrowe są zbudowane z bramek logicznych, które realizują funkcje algebry Boole’a. Na przykład bramki OR i AND mają po dwa wejścia i po jednym wyjściu, a bramka NOT ma jedno wejście i jedno wyjście.

W zależności od sygnałów otrzymywanych na wejściach bramki wytwarzają odpowiedni sygnał wyjściowy. W przypadku układów elektronicznych sygnałami są poziomy napięcia elektrycznego, „wysokie” napięcie oznacza 1, a „niskie” napięcie oznacza 0.

Kiedy więc bramka AND na jednym wejściu otrzyma sygnał wysoki (1), a na drugim niski (0), to na wyjściu wytworzy sygnał niski (0).

Bramka OR po otrzymaniu sygnału wysokiego (1) przynajmniej na jednym wejściu na wyjściu wygeneruje sygnał wysoki (1).

Natomiast bramka NOT zawsze wygeneruje sygnał przeciwny do tego, jaki otrzymała na wejściu.

Oprócz tych podstawowych typów bramek istnieją jeszcze inne, ale to już wykracza zbyt daleko poza interesujący nas temat. Warto tylko wiedzieć, że procesory są zbudowane z milionów mikroskopijnych bramek logicznych, które na najniższym poziomie odbierają sygnały elektryczne i na podstawie zasad algebry Boole’a przetwarzają je na inne sygnały elektryczne.

Wracając do tematu, na pewno już się zorientowałeś, że operatory logiczne PHP to po prostu reprezentacje działań algebry Boole’a.

Nazwa typu danych bool pochodzi od nazwiska uczonego Goerge’a Boole’a, który jest jednym z pionierów rodzaju logiki matematycznej, która stała się fundamentem budowy nowoczesnych układów cyfrowych.

Operatory logiczne PHP, jak również wszystkich innych języków programowania, działają dokładnie według tych samych zasad, co bramki logiczne w procesorze. Tylko zamiast sygnałów elektrycznych odbierają sygnały od programisty.

Sygnały te mają formę wyrażeń, które mogą mieć tylko jedną z dwóch wartości — prawda (1, sygnał wysoki) lub fałsz (0, sygnał niski). Po obliczeniu wartości argumentów operator otrzymuje dwie wartości wejściowe i na ich podstawie, zgodnie z logiką Boole’a, zwraca wartość wyjściową, czyli wynik.

Myślę że tyle teorii wystarczy, aby zrozumieć niektóre nurtujące początkujących programistów pytania w rodzaju „Skąd taka dziwna nazwa typu bool?”, „Czemu na && mówi się koniunkcja?” albo „Dlaczego właściwie XOR to inaczej alternatywa rozłączna?”.

Przy okazji, czym jest XOR skoro nie należy do podstawowych operacji algebry Boole’a? To też jest operator logiczny, tylko że nie zalicza się do trzonu trzech podstawowych działań.

Operatory && i and

Operatory and i && działają tak samo i różnią się tylko miejscem w kolejności wykonywania działań. Wersja && ma pierwszeństwo, a więc zostałaby wykonana wcześniej, gdyby obie znalazły się w tym samym wyrażeniu.

Czasami kolejność wykonywania działań ma bardzo duże znaczenie. Jeszcze do tego wrócę. A na razie dla uproszczenia posługuję się tylko operatorem &&.

Przypomnę, że operator && zwraca prawdę wtedy i tylko wtedy, gdy oba jego argumenty są prawdziwe.

Wyobraź sobie, że prowadzisz sklep internetowy i chcesz sprawdzić, czy klientowi należy się rabat. Warunki uzyskania rabatu są następujące (oba muszą być spełnione):

  1. Zamówienie przynajmniej 10 sztuk produktu.
  2. Klient należy do grupy VIP-ów.

Takie warunki bardzo łatwo można wyrazić za pomocą operatora PHP &&, np.:


$giveDiscount = $orderedQuantity > 9 && $clientType === "VIP";

Wynik tej instrukcji zależy od wartości zmiennych $quantity (liczba zamówionych sztuk) i $clientType (typ klienta). Wyobraź sobie, że klient zalogował się na konto VIP i złożył zamówienie na 8 sztuk produktu. Zatem do naszych zmiennych z serwera WWW trafiły następujące wartości:


$orderedQuantity = 8;
$clientType = "VIP";

Podsumowując, nasz skrypt w całości wygląda teraz tak:


$orderedQuantity = 8;
$clientType = "VIP";

$giveDiscount = $orderedQuantity > 9 && $clientType === "VIP";

Sprawdźmy, czy powinniśmy przyznać klientowi rabat w tej sytuacji:


var_dump($giveDiscount); // Wynik: bool(false)

Skrypt podpowiada nam, żeby nie dawać klientowi rabatu, ponieważ nie wszystkie warunki zostały spełnione.

Mając te informacje, możemy rozbudować nasz skrypt, aby zwiększyć swoje szanse na udaną sprzedaż. Najpierw sprawdzimy, ile sztuk produktu brakuje w zamówieniu, aby klientowi należał się rabat:


$minimumQuantity = 10; // Minimalna liczba sztuk w zamówieniu uprawniająca do otrzymania rabatu
$missingQuantity = $minimumQuantity - $orderedQuantity; // Obliczamy, ile sztuk brakuje

A teraz za pomocą poznanego w poprzednim rozdziale operatora trójargumentowego wyświetlamy klientowi odpowiedni komunikat w zależności od tego, ile sztuk produktu zamówił:


echo $missingQuantity > 0 ? "Zamów jeszcze $missingQuantity szt., a otrzymasz rabat." : "Gratulujemy dobrego wyboru. Należy ci się rabat.";

Teraz cały skrypt wygląda tak:


$orderedQuantity = 8;
$clientType = "VIP";

$giveDiscount = $orderedQuantity > 9 && $clientType === "VIP";

$minimumQuantity = 10; // Minimalna liczba sztuk w zamówieniu uprawniająca do otrzymania rabatu
$missingQuantity = $minimumQuantity - $orderedQuantity; // Obliczamy, ile sztuk brakuje

echo $missingQuantity > 0 ? "Zamów jeszcze $missingQuantity szt., a otrzymasz rabat." : "Gratulujemy dobrego wyboru. Należy ci się rabat.";

Operatory || i or

Z operatorami or i || jest tak samo, jak z operatorami and i &&, to znaczy różnią się tylko miejscem w kolejności wykonywania działań. Pierwszeństwo ma operator || i nim posługuję się w dalszych przykładach.

Operator PHP || zwraca prawdę, gdy przynajmniej jeden z jego argumentów jest prawdziwy.

Aby zilustrować jego działanie, posłużę się poprzednim przykładem. Prowadzimy ten sam sklep internetowy i organizujemy taką samą promocję, co poprzednio, ale odrobinę rozluźniamy warunki — aby otrzymać rabat wystarczy spełnić tylko jeden z poniższych warunków:

  1. zamówić przynajmniej 10 sztuk produktu lub
  2. być klientem VIP.

Tak moglibyśmy wyrazić te warunki za pomocą operatora ||:


$giveDiscount = $orderedQuantity > 9 || $clientType === "VIP";

To wszystko. Zmienna $giveDiscount będzie miała wartość true, gdy wartość zmiennej $orderedQuantity będzie większa od 9 (czyli przynajmniej 10, bo nie przewidujemy oferowania produktu w kawałkach) lub gdy zmienna $clientType będzie miała wartość typu łańcuchowego "VIP" lub jeśli będą spełnione oba te warunki jednocześnie.

Operator xor

Operator PHP xor ma tylko jedną wersję w tym języku, ale za to operacja, którą reprezentuje, szczyci się wyjątkowo dużą liczbą nazw, np. alternatywa rozłączna, alternatywa wyłączająca, alternatywa wykluczająca, różnica symetryczna itd. To jednak tylko taka ciekawostka bez większego znaczenia dla programisty.

Przypomnę, że operator PHP xor zwraca prawdę wtedy, gdy tylko jeden z jego argumentów jest prawdziwy, np.:


$x = 3;
$a = isset($x) xor isset($y);

Ten przykład reprezentuje pewien ważny niuans, który może sprawić, że otrzymasz całkiem inny wynik niż byś chciał.

Pewnie myślisz, że wynikiem tej operacji xor będzie true, ponieważ tylko jeden z argumentów ($x) jest prawdziwy (wynik wyrażenia isset($y) jest fałszywy, gdyż zmienna $y jest niezdefiniowana).

Jeśli tak, to częściowo masz rację. Rzeczywiście, zmienna $a otrzyma wartość true, ale z innego powodu niż ci się wydaje. Chodzi tu o kolejność wykonywania działań, którą sygnalizowałem wcześniej.

Pamiętasz, kiedy pisałem, że operatory && i || znajdują się wyżej w hierarchii kolejności wykonywania działań od operatorów and i or? Operatora xor też to dotyczy w tym sensie, że występuje on wyłącznie w tej „słabszej wersji”.

Operatory and, or i xor znajdują się na szarym końcu hierarchii, czyli w wyrażeniach są wykonywane jako ostatnie. To dokładnie tak samo, jak z działaniami arytmetycznymi, np.:

1 + 2 * 3 = ?

Jaki będzie wynik tego działania? Operator mnożenia zajmuje wyższą pozycję w hierarchii kolejności wykonywania działań, więc zostaje wykonany pierwszy. W związku z tym powyższe działanie jest równoważne z tym:

1 + (2 * 3) = 7

A teraz spójrz na naszą instrukcję z operatorem xor, do której też dodałem nawiasy, aby wyraźnie pokazać, w jakiej kolejności będą wykonywane działania:


($a = isset($x)) xor isset($y);

W tym działaniu mamy dwa operatory — operator przypisania (=) i operator xor. Operator = jest wykonywany przed operatorem xor. To znaczy, że ta instrukcja jest wykonywana następująco:

  1. Przypisanie zmiennej $a wartości wyrażenia isset($x) — jako że zmienna $x jest zdefiniowana, funkcja isset() zwraca true i ta wartość zostaje zapisana w zmiennej $a.
  2. Wykonanie operacji logicznej xor na argumentach $a i isset($y). Jednak wynik tej operacji jest już bez znaczenia, ponieważ nigdzie nie zostanie zapisany.
  3. Zwrócenie wartości zmiennej $a, którą jest wartość true zapisana w niej w kroku 1.

Teraz już rozumiesz, dlaczego wcześniej napisałem, że masz rację, ale tylko częściowo. Zmienna $a otrzymała wartość true nie jako wynik operacji xor, tylko jako wynik zwrócony przez wywołanie funkcji isset($x).

Jeśli nie wierzysz lub nadal nie do końca rozumiesz, o co w tym chodzi, to w miejsce wywołania funkcji isset($x) wstaw dowolne wyrażenie, a przekonasz się, że w zmiennej $a zawsze będzie znajdować się wartość tego wyrażenia, np.:


$a = 127 xor isset($y); 
echo $a; // 127

$a = "raz kozie śmierć" xor isset($y); 
echo $a; // raz kozie śmierć

Dla tego, co zostanie zapisane w zmiennej $a, część instrukcji od operatora xor nie ma żadnego znaczenia.

Jeśli chcesz uzyskać poprawny wynik, w przypadku operatora xor musisz zastosować nawias (w przypadku operatorów and i or wystarczy użyć „mocniejszych” wersji && i ||), np.:


$a = (isset($x) xor isset($y));

Teraz zmienna $a otrzyma wartość true zwróconą przez operator xor.

Morał z tej historii jest taki: w zdecydowanej większości przypadków lepiej jest używać operatorów && i || zamiast and i or, a podczas pracy z operatorem xor praktycznie zawsze poprawny wynik można uzyskać tylko dzięki użyciu nawiasów.

Operator negacji !

Ostatni z operatorów omówionych w tym rozdziale, operator negacji !, jest najprostszy.

Przypomnę, że odwraca on wartość logiczną wyrażenia, do którego zostanie zastosowany, np.:


$a = true;
var_dump(!$a); // Wynik: bool(false)

Na pierwszy rzut oka może się wydawać, że odwracanie wartości logicznej ma niewiele sensu, ale tak naprawdę ten operator przydaje się bardzo często.

Powiedzmy na przykład, że chcemy sprawdzić, czy użytkownik strony internetowej wpisał w formularzu swoje nazwisko. Jeśli nie, to chcemy mu wyświetlić odpowiednią reprymendę:


echo !isset( $_POST["name"]) ? "Podaj nazwisko" : "Podałeś nazwisko";

Operator PHP !, tak jak zresztą wszystkie operatory logiczne PHP, jest bardzo często używany w instrukcjach warunkowych, które już niedługo poznasz.

A teraz, na zakończenie tego rozdziału, opowiem ci o pewnej sztuczce, którą PHP stosuje przy obliczaniu wartości operatorów logicznych, aby ułatwić sobie pracę.

Skrócone wykonywanie działań logicznych

Operacje logiczne && i and oraz || i or mają tę charakterystyczną cechę, że czasami wystarczy poznać wartość tylko jednego argumentu, aby wiedzieć, jaki będzie wynik całej operacji. Weźmy na przykład takie wyrażenie:


false && isset($a)

Skoro operator && zwraca wartość true tylko wtedy, gdy oba jego argumenty mają wartość true, w tym przypadku już bez sprawdzania wartości drugiego argumentu wiadomo, że wynikiem wyrażenia będzie false.

Dlatego, jeśli pierwszy argument operatora && lub and ma wartość false, wartość drugiego argumentu nigdy nie jest sprawdzana.

To samo dotyczy operatorów || i or, tylko w drugą stronę, np.:


true || isset($a)

W tym wyrażeniu również funkcja isset() nie zostanie wywołana, ponieważ już po pierwszym argumencie można się zorientować, że wynikiem całej operacji będzie true — operator || zwraca prawdę, jeśli przynajmniej jeden z jego argumentów jest prawdziwy.

Dzięki takiemu sposobowi działania PHP zaoszczędza sobie trochę pracy, a tym samym zmniejsza obciążenie serwera i przyspiesza działanie stron internetowych.

Podsumowanie

  1. W PHP jest 6 operatorów logicznych: && i and (koniunkcja), || i or (alternatywa), xor (alternatywa rozłączna) i ! (negacja).
  2. Operatory && i and zwracają prawdę tylko wtedy, gdy oba ich argumenty są prawdziwe.
  3. Operatory || i or zwracają prawdę, gdy przynajmniej jeden z ich argumentów jest prawdziwy.
  4. Operator xor zwraca prawdę, gdy dokładnie jeden z jego argumentów jest prawdziwy.
  5. Działania z operatorem xor praktycznie zawsze należy umieszczać w nawiasie.
  6. Operator ! odwraca wartość swojego argumentu na przeciwną.
  7. Operatory && i || są wyżej w hierarchii kolejności wykonywania działań od operatorów and i or.
  8. Nazwa algebra Boole’a pochodzi od nazwiska uczonego George’a Boole’a.
  9. Algebra Boole’a używa trzech podstawowych działań, AND, OR i NOT, oraz dwóch wartości logicznych — prawda (0) i fałsz (1).
  10. Diagramy Venna przedstawiają wizualnie działania algebry Boole’a.
  11. PHP stosuje technikę skróconego wykonywania działań. Polega ona na tym, że jeśli wartość pierwszego argumentu pozwala poznać wartość całego wyrażenia, wartość drugiego argumentu nie jest już sprawdzana.



Pytania

  1. Jakie znasz operatory logiczne PHP? Wymień i krótko opisz każdy z nich.
  2. O czym należy pamiętać, gdy używa się operatorów and, or i xor?
  3. Jeśli operatory && i || znajdą się w jednym wyrażeniu z operatorami and, or i xor, to które zostaną wykonane wcześniej?
  4. Skąd wzięła się nazwa typu danych bool?
  5. Jakie są trzy podstawowe działania i dwie wartości algebry Boole’a?
  6. Czym są diagramy Venna?
  7. Na czym polega technika skróconego wykonywania działań logicznych stosowana przez PHP?



Ćwiczenia

  1. Utwórz tabelę prawdy dla operatora xor.
  2. Wyobraź sobie, że zmienna $quantity zawiera liczbę zamówionych sztuk produktu przez użytkownika sklepu internetowego.

    Napisz instrukcję PHP, która wyświetla napis "W sam raz", jeśli podana wartość jest większa od 20 i mniejsza od 50, lub "Niewłaściwa ilość" w pozostałych przypadkach.

Podobał Ci się ten artykuł?

Oceń go!

Średnia 5 / 5. Liczba głosów: 2

Jeszcze nikt nie głosował. Wyprzedź innych i zagłosuj.

Skoro spodobał Ci się ten artykuł...

Poleć go znajomym!

Ojej :( Powiedz nam, co powinniśmy poprawić!

Podoba Ci się ta strona?

Pomóż nam się rozwijać, wykupując płatne konto. Dzięki temu będziemy mogli tworzyć dla Ciebie jeszcze więcej ciekawych treści, a Ty pozbędziesz się reklam.

Subskrybuj
Powiadom o
guest

0 Komentarze
Najstarsze
Najnowsze Najwięcej głosów
Opinie w linii
Zobacz wszystkie komentarze
0
Chętnie poznam Twoje przemyślenia, skomentuj.x