Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Tablice w php 5.2.0, Elementy tablic nie dodają się tak jak w php 5.1.1: $aArray[]
Athlan
post
Post #1





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Witam Was… Ostatnio zainstalowałem sobie nowy serwer (zrobiłem update) z php 5.1.1 na 5.2.0. W rezultacie połowa tablic przestała mi działać… pięknie co? Powiem szczeże że się zdenerwowałem jak nic… już kilka dni badam o co chodzi. Przykładowy kod z widoku mojego frameworka:

  1. <?php
  2. $oView->aError = array(); //declare an array
  3. var_dump($oView->aError); // it will output: Array( )
  4.  
  5. $oView->aError[] = '1';  // add element to array...
  6. $oView->aError[] = 2;  // ... some int? ...
  7. $oView->aError[] = '3';  // ... and string ...
  8.  
  9. var_dump($oView->aError); // it output: Array( )
  10. // hmmm, it should output: Array( [0] => string(1), "1" [1] => int(1), "2" => string(1) "3" )
  11. ?>


Obiekt $oView oczywiście został wcześniej zainicjowany. Przejdźmy do rzeczy… Zaraz po zadeklarowaniu tablicy sprawdzamy ją tak dla pewności, że jest. „No dziwne by było żeby jej nie było” (masło maślane ale prawda sama w sobie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) )

Ok. jedziemy dalej… dodajemy do tablicy kolejne elementy poprzez użycie [] – co to oznacza każdy wie. Po dodaniu elementów lumpujemy tablice po raz kolejny. O dziwo jest pusta (IMG:http://forum.php.pl/style_emoticons/default/blink.gif) .

Przypominam, że zrobiłem update z php 5.1.1 na 5.2.0. Czyżby wlepili tam jakiegoś buga? Zaraz po updacie ta część kodu przestała działać. Podobnie warstwa ACL, gdzie klasa User w podobny sposób sama sobie dodaje grupy użytkownika – dziwiłem się, że do żadnego kontrolera nie mam dostępu (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Teraz wszystko jasne. Zainteresowało mnie to, przeprowadziłem testy. Napisałem dwa przykłady, które działają…

Test 01:
  1. <?php
  2. $aArray = array();
  3.  
  4. $aArray[1] = 'first element';
  5. $aArray[2] = 'second element';
  6. $aArray[3] = 'third element';
  7.  
  8. var_dump($aArray);
  9. ?>


Test 02:
  1. <?php
  2. class ArrayTest
  3. {
  4. private $aAttributes = array();
  5.  
  6. public function __construct()
  7. {
  8. $this->aAttributes['TestCase'] = array();
  9. }
  10.  
  11. public function __destruct()
  12. {
  13. var_dump($this->aAttributes['TestCase']);
  14. }
  15.  
  16. public function __get($sName)
  17. {
  18. return $this->aAttributes['TestCase'][$sName];
  19. }
  20.  
  21. public function __set($sName, $mValue)
  22. {
  23. return $this->aAttributes['TestCase'][$sName] = $mValue;
  24. }
  25. }
  26.  
  27. $oArrayTest = ArrayTest();
  28.  
  29. $oArrayTest->FirstElement = 1;
  30. $oArrayTest->SecondElement = 2;
  31. $oArrayTest->ThirdElement = 3;
  32. ?>

Co jest nie tak? Może załącze jeszcze klase mojego widoku I usera, aby pokazać, że dodaję elementy w taki sam sposób:

User Class (patrz metody setGroup(), hasGroup(), getGroup() )
http://phpfi.com/179458
View Class (patrz metody __get(), __set() )
http://phpfi.com/179456

Ten post edytował Athlan 28.11.2006, 16:37:22
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Athlan
post
Post #2





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Dziś odkryłem swój błąd, który popełniłem przy tworzeniu tablic. Pokażę to na poniższym przykładzie:

  1. <?php
  2.  
  3. class ArrayTest
  4. {
  5. private $_aAttributes = array();
  6.  
  7. public function __get($sName)
  8. {
  9. return $this->_aAttributes[$sName];
  10. }
  11.  
  12. public function __set($sName, $mValue)
  13. {
  14. return $this->_aAttributes[$sName] = $mValue;
  15. }
  16. }
  17.  
  18. $oArray = new ArrayTest();
  19.  
  20. $oArray->test = array();
  21. $oArray->test[] = 'test1';
  22. $oArray->test[] = 'test2';
  23. $oArray->test[] = 'test3';
  24.  
  25. var_dump($oArray->test);
  26.  
  27. ?>


Dump tablicy wykaże pustą – ma wykazać. Dlaczego? Do metody __get() dostaje się atrybut test – ok. Następnie deklarujemy atrybut test[]. Co pomyśli sobie __set() i __get() ? Dla zmiennej $sName oznacza po prostu $this->_aAttributes[test[]], a powinno $this->_aAttributes[test][]. Po części prawda, po części paradoks. Moim zdaniem php zamo sobie powinno wrzucać elementy w tablice przy __set() i __get(), no ale skoro nie… Więc jak można rozwiązać powyższy przykład? Ano bardzo podobnie, budowa klasy nie zmieni się:

  1. <?php
  2.  
  3. // …
  4.  
  5. $oArray = new ArrayTest();
  6.  
  7. $aArray = array();
  8. $aArray[] = 'a';
  9. $aArray[] = 'b';
  10. $aArray[] = 'c';
  11.  
  12. $oArray->test = $aArray;
  13.  
  14. var_dump($oArray->test);
  15. ?>


Teraz działa? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Sam jestem zaskoczony, można z tego wyciągnąć jakiś wniosek, dla mnie jest jednoznaczny: twórcy php engine nie popisali się pod tym względem, nie możemy operować na tablicach obiektu poprzez metodę __set(). Teoretycznie nawet nie powinniśmy, ba co przyjmie pierwszy argument tej funkcji? Przyjmie Stinga jak ma się nazywać zmienna (kolejny element tablicy private $_aAttributes. Teoretycznie nie powinno działać, ale ja i tak wnoszę sprzeciw. Takie jest moje zdanie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Tak więc prostuje moje poprzednie pytanie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) . Fajnie jest dojść do takiego wniosku, więc zachęcam innych do tworzenia mnóstwa przykładów odwzorowujących kawałek naszego kodu, który rzekomo nie działa. To nauczka dla mnie, jak i przykład dla młodych programistów. Szczerze po tej wypowiedzi w ogóle nie wstydzę się pytania którego zadałem, gdyż nikt nie był w stanie mi na nie odpowiedzieć – nie ma pola do wstydu (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)

Dziwną rzeczą jednak jest to, że kolizja wystąpiła dopiero w php 5.2.0, a w poprzedniej (mojej) wersji na serwerze 5.1.1 rzekomy błąd nowego pokolenia php 5 gładko działał. Zapraszam do dyskusji na ten temat w tym topicku – może ktos wie coś na owy przypadek traktowania zmiennych __set() w pierwszym parametrze.

Pozdrawiam, Athlan (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)


----- [EDIT] -----

P.S.

Jak wspomniałem w pytaniu, przez to padł mi ACL a precyzując: klasa User, która nadawała grupy użytkownikowi do sesji. Kod wyglądał następująco:

  1. <?php
  2. public function setGroup()
  3. {
  4. $aGroups = func_get_args();
  5.  
  6. foreach($aGroups as $iKey => $sValue)
  7. {
  8. $this->_oUserSessionInfo->groups[] = $sValue;
  9. }
  10. }
  11. ?>


Jak widać, sesja $this->_oUserSessionInfo jest obiektem (po prefiksie wiedeńskim). Zmienna groups[] przyjmowana jest do klasy sesji poprzez metodę __set() w pierwszym jej parametrze. Wczesniej udowodniłem, że tak nie może być… jak rozwiązać problem? Ano namotamy trochę w kodzie – ale będzie działało.

  1. <?php
  2. public function setGroup()
  3. {
  4. $aGroups = func_get_args();
  5.  
  6. foreach($aGroups as $iKey => $sValue)
  7. {
  8. $aArray = $this->_oUserSessionInfo->groups;
  9. $aArray[] = $sValue;
  10. $this->_oUserSessionInfo->groups = $aArray;
  11. }
  12. }
  13. ?>


Najpierw pobieramy tablicę $aArray z sesji jako tablica grup. Potem wykonujemy operację dodania grupy już poza klasą nie używając metody __set(), po czym tablice ponownie zapisujemy do __set()’a. Innego sposobu nie ma… ale jakiegoś haka udało mi się wymyślić.

Ten post edytował Athlan 30.11.2006, 17:07:18
Go to the top of the page
+Quote Post

Posty w temacie


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: 18.01.2026 - 14:20