Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Pułapki w PHP
michalg
post
Post #1





Grupa: Zarejestrowani
Postów: 122
Pomógł: 8
Dołączył: 20.10.2008

Ostrzeżenie: (0%)
-----


Witam,

Ostatnio w pracy natknęliśmy się na pewien problem, który z pozoru może być niezrozumiały na pierwszy rzut oka. Choć zachowanie to jest prawidłowe i zupełnie uzasadnione. Chodzi o problem foreacha "psującego" tablice (oczywiście problem wystąpił w dużo bardziej złożonym kodzie, ten jest tylko przykładem):

  1. <?php
  2. $tablica = array('1', '2', '3');
  3.    
  4.    foreach($tablica as &$element) {}
  5.  
  6.    foreach($tablica as $element) {}
  7.    
  8.    print_r($tablica);
  9. ?>


Rezultat 1, 2, 2 może wydawać się nieprawidłowy, lecz wszystko działa prawidłowo. Nie napiszę tu, dlaczego tak jest, żeby osoby, które nigdy się z tym nie zetknęły mogły same dojść do tego, co się stało winksmiley.jpg

Znacie jeszcze jakieś takie ciekawe smaczki w PHP?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 13)
Maciekbjw
post
Post #2





Grupa: Zarejestrowani
Postów: 217
Pomógł: 23
Dołączył: 2.12.2007
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Ameryki nie odkryliście smile.gif

Hmm, co do smaczków winksmiley.jpg

Ciekawym jest, że w operatorze ternariuszu nie można używać echo -> http://www.kacka.pl/index.php?showtopic=24


--------------------
Masz swoje mieszkanie i chcesz je wynająć? Sprawdź ofertę Zarzadządzanie Najmem

WRONA.IT - pozycjonowanie stron
www.ecyklopedia.pl
Go to the top of the page
+Quote Post
michalg
post
Post #3





Grupa: Zarejestrowani
Postów: 122
Pomógł: 8
Dołączył: 20.10.2008

Ostrzeżenie: (0%)
-----


Cytat(Maciekbjw @ 26.02.2009, 19:00:36 ) *
Ameryki nie odkryliście smile.gif


W to nie wątpię winksmiley.jpg

Cytat(Maciekbjw @ 26.02.2009, 19:00:36 ) *
Hmm, co do smaczków winksmiley.jpg

Ciekawym jest, że w operatorze ternariuszu nie można używać echo -> http://www.kacka.pl/index.php?showtopic=24


Ciekawe, choć uzasadnienie jest trochę mylące. Powodem raczej nie jest to, że ternariusz musi coś zwracać, tylko to, że echo nie jest funkcją tylko specjalną kontstrukcją języka.

Często, można się też przejechać na porównaniach i niejawnym rzutowaniu typów, np mogłoby się wydawać, że coś takiego będzie porównywać dwa stringi:
  1. <?php
  2. if ("1.00" == "1.0") echo "ROWNE\n";
  3.    if ("001" == "01") echo "ROWNE\n";
  4. ?>


Oczywiście w dokumentacji jest opisane, że w tych wypadkach rzutowanie jest na typy numeryczne.

Inna pułapka, niekoniecznie związana z PHP, ale z arytmetyką zmiennoprzecinkową, to to, że przykładowo dwa nie zawsze jest równe dwa:

  1. <?php
  2. $a = 1;
  3.  
  4.    while ($a < 3) {
  5.    $a += 0.1;
  6.  
  7.    echo $a."\n";    
  8.        if ($a == 2.0) {
  9.        echo "a == 2\n";
  10.        }
  11.  
  12.        if (round($a, 5) == 2.0) {
  13.        echo "round(a, 5) == 2\n";
  14.        }
  15.  
  16.    }
  17. ?>
Go to the top of the page
+Quote Post
kodereq
post
Post #4





Grupa: Zarejestrowani
Postów: 87
Pomógł: 0
Dołączył: 27.02.2009

Ostrzeżenie: (0%)
-----


Cytat
Rezultat 1, 2, 2 może wydawać się nieprawidłowy, lecz wszystko działa prawidłowo.


Mógłbym jednak poprosić o wyjaśnienie przykładu ?
Go to the top of the page
+Quote Post
mike
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Cytat(michalg @ 26.02.2009, 19:30:39 ) *
Powodem raczej nie jest to, że ternariusz musi coś zwracać, tylko to, że echo nie jest funkcją tylko specjalną kontstrukcją języka.
Nie. Uzasadnienie, które podważasz jest poprawne. Twoje jest niepoprawne.
print() podobnie jak echo() jest konstrunkcją językową w PHP ale zwraca wartość. Dlatego można go w omawianej sytuacji użyć.
Go to the top of the page
+Quote Post
bazyliszek83
post
Post #6





Grupa: Zarejestrowani
Postów: 81
Pomógł: 6
Dołączył: 24.07.2007
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Cytat(kodereq @ 27.02.2009, 10:15:12 ) *


Mógłbym jednak poprosić o wyjaśnienie przykładu ?


Wszystko wyjaśnione jest w manualu:
Cytat
Warning

Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().


--------------------
App 4 You - Aplikacje internetowe
Go to the top of the page
+Quote Post
ucho
post
Post #7





Grupa: Zarejestrowani
Postów: 300
Pomógł: 32
Dołączył: 31.07.2006

Ostrzeżenie: (0%)
-----


Proszę bardzo: http://pl.php.net/foreach . Osobiście uważam że ten kto wymyślił takie a nie inne zachowanie php powinien oberwać. O http://pl.php.net/manual/pl/types.comparisons.php nie wspominając smile.gif
Go to the top of the page
+Quote Post
wookieb
post
Post #8





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Ja bym jednak polecał troszkę jaśniejsze wyjaśnienie które zobrazuje przypadek.
http://i-code-today.blogspot.com/2009/02/p...references.html

Cytat
Osobiście uważam że ten kto wymyślił takie a nie inne zachowanie php powinien oberwać

Też tak uważałem ale czasem coś takiego może się nawet przydać.

Co do porównywania typów to mam co do tego dobre uczucia. Nie musisz się bawić z konwersja przy porównywaniach. Robi to za ciebie silnik. Jeżeli ktoś zna zasady porównywania to nie sprawi mu to żadnego kłopotu.

Kolejny przykład.
http://forum.php.pl/index.php?showtopic=112957

Ten post edytował wookieb 27.02.2009, 11:15:25


--------------------
Go to the top of the page
+Quote Post
michalg
post
Post #9





Grupa: Zarejestrowani
Postów: 122
Pomógł: 8
Dołączył: 20.10.2008

Ostrzeżenie: (0%)
-----


Witam,

Cytat(mike @ 27.02.2009, 10:30:52 ) *
Nie. Uzasadnienie, które podważasz jest poprawne. Twoje jest niepoprawne.


Skoro to uzasadnienie (że ternariusz musi coś zwracać) jest poprawne, to dlaczego poniższy fragment kodu działa?
  1. <?php
  2. $a = (true) ? flush() : flush();
  3.    
  4.    var_export($a);
  5. ?>


Funkcja flush nie zwraca żadnej wartości. W efekcie ternariusz również nie zwraca wartości. A jednak działa - dlaczego?

Cytat(mike @ 27.02.2009, 10:30:52 ) *
print() podobnie jak echo() jest konstrunkcją językową w PHP ale zwraca wartość. Dlatego można go w omawianej sytuacji użyć.


Racja, print() również jest konstrukcją językową. Ale to, że zwraca wartość nie ma tutaj znaczenia - ważne jest to, że zachowuje się jak funkcja. Równie dobrze print() mogłby nie zwracać wartości, ale póki miałby charakter funkcji, to mógłby być używany m.in. w ternariuszu.
Go to the top of the page
+Quote Post
erix
post
Post #10





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
to dlaczego poniższy fragment kodu działa?

Nie działa, gdyż $a ma wartość null. winksmiley.jpg

Analogicznie:
  1. <?php
  2. var_dump($jakasNieistniejacaZmienna);
  3. ?>

też zwraca null.


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
michalg
post
Post #11





Grupa: Zarejestrowani
Postów: 122
Pomógł: 8
Dołączył: 20.10.2008

Ostrzeżenie: (0%)
-----


Cytat(erix @ 2.03.2009, 17:01:55 ) *
Nie działa, gdyż $a ma wartość null. winksmiley.jpg


Działa w takim sensie, że nie powoduje błędu - tak, jak dzieje się w przypadku użyciu echo. Bo dyskusja dotyczy właśnie tego, dlaczego w ternariuszu nie działa echo.
Go to the top of the page
+Quote Post
erix
post
Post #12





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
echo() is not actually a function (it is a language construct)

Przy flush" title="Zobacz w manualu PHP" target="_manual takiej wzmianki nie znalazłem. Wszystko jest w porządku.


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
michalg
post
Post #13





Grupa: Zarejestrowani
Postów: 122
Pomógł: 8
Dołączył: 20.10.2008

Ostrzeżenie: (0%)
-----


Cytat(erix @ 2.03.2009, 17:10:28 ) *
Przy flush" title="Zobacz w manualu PHP" target="_manual takiej wzmianki nie znalazłem. Wszystko jest w porządku.


No i właśnie do tego dążę. Że echo nie działa w ternariuszu nie dlatego, że ternariusz musi zwracać wartość (jak widać na moim przykładzie, nie musi), tylko że echo jest specjalną konstrukcją, której nie można używać jak funkcji.
Go to the top of the page
+Quote Post
ucho
post
Post #14





Grupa: Zarejestrowani
Postów: 300
Pomógł: 32
Dołączył: 31.07.2006

Ostrzeżenie: (0%)
-----


Apropo flush() - nawet jak nie użyliście echo ani nic takiego to flush spowoduje wysłanie nagłówków http - raz przez to strasznie się głowiłem dlaczego mam ciągle "headers already sent" tongue.gif
I jedna "pułapka" - zachowanie php które jest kompletnie logiczne, tylko nikt o tym nie wie/nie pamięta. Otóż jeśli nasz użytkownik otworzy np. 10 podstron naszego serwisu to wszystkie, z wyjątkiem aktualnie aktywnego żądania, będą wisieć na session_start(). PHP dba w ten sposób o spójność danych w $_SESSION ale może to zrobić kuku, kiedy jedna z podstron ładuje się długo. Należy używać session_write_close(), kiedy wiemy, że już nic w sesji zmieniać nie będziemy.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 12:40