Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Nieintuicyjne zachowanie foreach, błąd php czy złe oczekiwania
mike
post
Post #1





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

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


Witam,

Chciałbym się podzielić pewnym spostrzeżeniem. Kawałek kodu na początek:
  1. <?php
  2.  
  3. $strColumn = 'surname';
  4.  
  5. $arrColumns = array( 'surname', 'name', 'email' );
  6.  
  7. foreach( $arrColumns as $intId => $strColumn )
  8. {
  9. echo $intId . ' => ' . $strColumn . '<br />';
  10. }
  11.  
  12. echo '<br />' . $strColumn; // wyświetli `email` a powinno wyświetlić `surname`
  13.  
  14. ?>

Powiedzcie mi czy ja za wiele wymagam, żeby lokalna zmienna $strColumn była faktycznie lokalna?
Dlaczego się czepia wcześniej ustawionej zmiennej?

Czy to jets bug php czy jest to błąd w mojej interpretacji i moich oczekiwaniach?

Już klika lat piszęw php i dopiero teraz to zauważyłem, ...., a może wcześniej nie miałem nigdy takiej sytuacji, ..., ale to raczej wykluczone.

Wersja php na jakiej pracuję to 5.1.2.

(tylko bez głupich komentaży o Przedszkolu (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) )
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
pEbE
post
Post #2





Grupa: Zarejestrowani
Postów: 106
Pomógł: 3
Dołączył: 21.03.2006
Skąd: Sosnowiec

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


No nic dziwnego jak zmieniasz wartosc zmiennej...
Go to the top of the page
+Quote Post
nospor
post
Post #3





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




zmienne lokalne dotyczą funkcji, a nie kawalkow kodu objętych {}. No przykro mi, ale to trafia na przedszkole (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
http://pl.php.net/manual/pl/language.variables.scope.php
Go to the top of the page
+Quote Post
mike
post
Post #4





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

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


No kurcze,

aż dziw bierze że dopiero teraz mi się to przytrafiło (IMG:http://forum.php.pl/style_emoticons/default/laugh.gif)

Człowiek uczy się całe życie.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

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


Stane w obronie mike_mecha: patrzcie na to (C++ nie C):
Kod
#include <stdio.h>

int main()
{
        int i = 2323;
        for ( int i = 0; i < 10; i++ )
        {
                printf( "i = %d\n", i );

        }

        printf( "\ni = %d", i );
        return 0;
}


Kod
$ ./C.bin
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9

i = 2323


Skoro php jest bazowane na C/C++ mozna bylo oczekiwac takiego zachowania (no chyba za na jakiejs stronie manuala 4pt czcionka jest napisane ze to dziala inaczej (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) )
Go to the top of the page
+Quote Post
mike
post
Post #6





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

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


Dokładnie coś takiego miałem na myśli skoro w konstrukcji
Kod
foreach(wyrażenie_tablicowe as $klucz => $wartość)

Podczas każdej iteracji $klucz otrzymuje wartość aktualnego klucza a $wartość otrzymuje wartość aktualnego elemantu tablicy i są to zmienne jakoby lokalne dla pętli foreach to nie powinny się czepiać tego co na zewnątrz.

Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do niby dlaczego nie jest od nas wymagane pisanie:
  1. <?php
  2.  
  3. $arrColumns = array( 'surname', 'name', 'email' );
  4.  
  5. $intId  = null; // wcześniejsza deklaracja zmiennych, to oczywiście nie ma sensu
  6. $strColumn = null; // ale jeśli wartość byłaby tablicą to już tak
  7. foreach( $arrColumns as $intId => $strColumn )
  8. {
  9. echo $intId . ' => ' . $strColumn . '<br />';
  10. }
  11.  
  12. ?>

Ja uważam zachowanie php w tym miejscu za nieintuicyjne.
Go to the top of the page
+Quote Post
nospor
post
Post #7





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do nieby dlaczergo nie jest od nas wymagane pisania:
Ale czemu? php nie wymaga inicjacji (zadeklarowania) zmiennej, przed przypisaniem jej wartości

ps: przenosze na php bo mnie zywcem zjecie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

edit: no i dla mnie to nie jest nieintuicyjne. normalka. lokale w funkcjach, wszystko inne nie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
mike
post
Post #8





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

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


Cytat(nospor @ 2006-03-21 14:55:03)
Cytat
Ja to uważam za niekonsekwencję, bo skoro jest tak jak jest do nieby dlaczergo nie jest od nas wymagane pisania:
Ale czemu? php nie wymaga inicjacji (zadeklarowania) zmiennej, przed przypisaniem jej wartości

Oj, no wiesz. Tego to mi mówić nie musisz.

Chodziło mi w tym przykładzie (który jest trochę bardziej hipotetyczny niż realny), że skoro to co jest wewnątrz pętli foreach wpływa na resztę to powinno to być powiedziane.

A po za tym. Zmienne tablicowe trzeba deklarować wcześniej bo dostaniesz E_NOTICE. I dokładnie o to mi chodziło (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)

Nieintuicyjne. Może nie aż tak bardzo. Po prostu miałem taką sytuację, że mnie to zaskoczyło. I uświadomiłem sobie że nie jest to najlepiej rozwiązane.
Go to the top of the page
+Quote Post
nospor
post
Post #9





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
A po za tym. Zmienne tablicowe trzeba deklarować wcześniej bo dostaniesz E_NOTICE.
zmienne tablicowe tak. ale od kiedy index tablicy to tablica? pozatym foreach inicjuje to sam w sobie.
No i pozatym tablice napewno nie inicjuje się przez przypisanie jej null'a (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
scanner
post
Post #10





Grupa: Zarząd
Postów: 3 503
Pomógł: 28
Dołączył: 17.10.2002
Skąd: Wrocław




Jesli dobrze pamiętam ze szkoły (dawno nie praktykowałem C++) to tam można zrobić lokalny fragment kodu poprzez samo postawienie klamer - wszystko co wewnątrz nich jest jest lokalne i już.
Go to the top of the page
+Quote Post
MaKARON
post
Post #11





Grupa: Zarejestrowani
Postów: 114
Pomógł: 1
Dołączył: 17.07.2003

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


Sto lat temu to robilem, ale przegladalem zrodla kernela linuksa i wydaje mi sie, ze w C tez mozna cos takiego zrobic, ale uzywalo sie haka:

do {
// tutaj kod
} while( 0 );
Go to the top of the page
+Quote Post
mike
post
Post #12





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

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


Cytat(nospor @ 2006-03-21 15:01:34)
(...) zmienne tablicowe tak. ale od kiedy index tablicy to tablica? pozatym foreach inicjuje to sam w sobie.

Tu chodziło mi o wartości, które tablicami już mogą być :-)

A właśnie o to "sam w sobie" mi chodzi. Skoro on robi do własnych celów to powinno być to o zasięgu lokalnym.
Go to the top of the page
+Quote Post
kszychu
post
Post #13





Grupa: Przyjaciele php.pl
Postów: 2 712
Pomógł: 23
Dołączył: 27.10.2003
Skąd: z kontowni

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


MIke, zupełnie nie rozumiem, dlaczego takie zachowanie foreach jest dla Ciebie dziwne. Przecież dokładnie tak samo działają inne pętle (for).
Poza tym, napisałeś, że tablice trzeba wcześniej deklarować.... niekoniecznie:
  1. <?php
  2.  
  3. $tablica[] = $wartosc; // to wywali notice
  4. $tablica[$indeks] = $wartosc; // ale to już nie
  5.  
  6. ?>
Go to the top of the page
+Quote Post
anopak
post
Post #14





Grupa: Zarejestrowani
Postów: 124
Pomógł: 0
Dołączył: 26.10.2004
Skąd: Rybnik

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


z jednej strony mike ma rację, bo np jeżeli includujemy jakiś kod z pętlą forech i nie wiemy jakie tam są zmienne, to może nam to nieźle namieszać w kodzie...

co do tablice, to:
  1. <?php
  2. $tablica[]=1;
  3. $tablica[$in]=2;
  4.  
  5. ?>


nie wyrzyca mi błędów E_NOTICE, ani pierwsze ani drugie...

Ten post edytował anopak 22.03.2006, 00:36:18
Go to the top of the page
+Quote Post
nospor
post
Post #15





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
bo np jeżeli includujemy jakiś kod z pętlą forech i nie wiemy jakie tam są zmienne, to może nam to nieźle namieszać w kodzie...
Ale co to za argumentacja? Rownie dobrze mozemy includowac kod bez pętli i nie wiedziec jakie ma zmienne i tez moze nam "namieszac w kodzie" (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
bigZbig
post
Post #16





Grupa: Zarejestrowani
Postów: 740
Pomógł: 15
Dołączył: 23.08.2004
Skąd: Poznań

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


mike_mecha zaskoczylo takie zachowanie poniewarz przenosi swoje doswiadczenia z innych jezykow na php, ale w php jest to wlasnie w ten sposob ustalone, co mnie akurat wydaje sie calkiem logiczne bo jesli klamry mialyby okreslac granice zasiegu zmiennych to przy pelnej konsekwencji powinnismy otrzymac cos takiego:
  1. <?php
  2. $aA = array('kicha', 'micha', 'rycha');
  3. $aB = array('bleble');
  4. foreach($aA as $sKey => $sValue) {
  5. //powinna nastapic inicjalizacja zmiennej lokalnej
  6. $aB[$sKey] = 'my_'.$sValue;
  7. }
  8. print_r($aB);
  9. //powinno zwrocic array('0' => 'bleble');
  10. ?>


Zauwazcie ze w php nie trzeba inicjalizowac zmiennych dlatego gdyby klamry wyznaczaly zasieg zmiennych php musialoby podjac decyzje czy tablica $aB jest kontynuacja zmiennej zainicjalizowanej poza petla, czy nalezy zainicjalizowac nowa zmienna.

W ActionScripcie jest to rozwiazane dzieki instrukcji var inicjalizujacej zmienna
Kod
i:Number = 10;
A_array = new Array(1, 2, 3);

for(var i:Number = 0; i < A_array.length; i++) {
  // zwroci kolejno 0 1 2
  trace(i);
}

// zwroci 10
trace(i);

for(i = 0; i < A_array.length; i++) {
  // zwroci kolejno 0 1 2
  trace(i);
}

// zwroci 2
trace(i);
Go to the top of the page
+Quote Post
anopak
post
Post #17





Grupa: Zarejestrowani
Postów: 124
Pomógł: 0
Dołączył: 26.10.2004
Skąd: Rybnik

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


Cytat(nospor)
Ale co to za argumentacja? Rownie dobrze mozemy includowac kod bez pętli i nie wiedziec jakie ma zmienne i tez moze nam "namieszac w kodzie"


yh, faktycznie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Cytat(bigZbig)
Zauwazcie ze w php nie trzeba inicjalizowac zmiennych dlatego gdyby klamry wyznaczaly zasieg zmiennych php musialoby podjac decyzje czy tablica $aB jest kontynuacja zmiennej zainicjalizowanej poza petla, czy nalezy zainicjalizowac nowa zmienna.


no niby tak jest, ale mogłoby to być rozwiązane np tak:
  1. <?php
  2.  
  3. foreach($tablica){
  4.  echo $this->key .'=>'.$this->value.'<br>';
  5. }
  6.  
  7. ?>


i wtedy nie było by problemów z nadpisaniem zmiennych, tylko byłby kolejny problem z wykorzystaniem takiej konstrukcji w klasach (IMG:http://forum.php.pl/style_emoticons/default/sad.gif)

Ten post edytował anopak 22.03.2006, 12:26:41
Go to the top of the page
+Quote Post
bigZbig
post
Post #18





Grupa: Zarejestrowani
Postów: 740
Pomógł: 15
Dołączył: 23.08.2004
Skąd: Poznań

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


@anopak - sam sobie odpowiedziales
Go to the top of the page
+Quote Post
anopak
post
Post #19





Grupa: Zarejestrowani
Postów: 124
Pomógł: 0
Dołączył: 26.10.2004
Skąd: Rybnik

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


@bigZbig - no niby tak, ale to mogły być poprostu zmienne zarezerwowane (tak jak $this)... no cóż może w któreś wersji ogólnie będzie to inaczej rozwiązane (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
bigZbig
post
Post #20





Grupa: Zarejestrowani
Postów: 740
Pomógł: 15
Dołączył: 23.08.2004
Skąd: Poznań

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


@anopak - no OK, ale potrzebne Ci to? Moim zdaniem wystarczy izolowanie zmiennych w funkcjach i klasach.

Ten post edytował bigZbig 22.03.2006, 15:02:46
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 22.08.2025 - 15:54