Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Tablice w php 5.2.0, Elementy tablic nie dodają się tak jak w php 5.1.1: $aArray[]
Athlan
post 28.11.2006, 16:36:20
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 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 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 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


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
koala
post 29.11.2006, 00:17:53
Post #2





Grupa: Zarejestrowani
Postów: 23
Pomógł: 0
Dołączył: 4.03.2005

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


Witam
Nie instalowałem jeszcze 5.2 ale tutaj : http://www.php.net/UPDATE_5_2.txt znalazłem coś takiego :

New functions
=============

In the php core
===============
array array_fill_keys(array keys, mixed val)
- Create an array using the elements of the first parameter as keys, each initialized to val

i tak sobie pomyślałem czy nie o to chodzi ?
W działających przykładach podałeś i klucze i wartości a w pierwszym nie działającym nie podajesz kluczy (tak się do teraz robi) może w 5.2 nie da się już $oView->aError[] ? tyko trzeba podać klucz ?


--------------------
php 5.1.6
Go to the top of the page
+Quote Post
hugo_amv
post 29.11.2006, 12:44:33
Post #3





Grupa: Zarejestrowani
Postów: 32
Pomógł: 0
Dołączył: 22.06.2005
Skąd: Lublin

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


Witam
Rozwiazaniem tego problemu jest użycie funkcji array_push.


--------------------
DzbanyIT blog programisty
Go to the top of the page
+Quote Post
Jarod
post 29.11.2006, 15:04:48
Post #4





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Pytanie dlaczego nie można przypisywać elementu w zwykły sposób.. :/


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
Cysiaczek
post 29.11.2006, 15:29:03
Post #5





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Potestowałem troszkę i nie zauważyłem różnic w obsłudze tablic ;| Może wina leży po stronie metod magicznych, albo gdzieś coś Twój framework gubi?


--------------------
To think for yourself you must question authority and
learn how to put yourself in a state of vulnerable, open-mindedness;
chaotic, confused, vulnerability, to inform yourself.
Think for yourself. Question authority.
Go to the top of the page
+Quote Post
hwao
post 29.11.2006, 19:19:42
Post #6


Developer


Grupa: Moderatorzy
Postów: 2 844
Pomógł: 20
Dołączył: 25.11.2003
Skąd: Olkusz




Musi Ci wywalać gdzieś jakiś errro, daj PEŁNE raportowanie i się dowiesz. Na pewno nic w php nie zmienili, gdyż mi działa wszystko ok.
Go to the top of the page
+Quote Post
Ace
post 30.11.2006, 10:15:29
Post #7





Grupa: Zarejestrowani
Postów: 216
Pomógł: 0
Dołączył: 9.08.2003
Skąd: Warszawa

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


$oArrayTest = ArrayTest();

a nie powinno byc

$oArrayTest = new ArrayTest();

?
Go to the top of the page
+Quote Post
Athlan
post 30.11.2006, 17:06:19
Post #8





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? 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 smile.gif

Tak więc prostuje moje poprzednie pytanie 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 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 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


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
cassis
post 4.12.2006, 08:33:00
Post #9





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 4.12.2006

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


Proponuje zamiast tablic w tym przypadku użyć ArrayObject

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


Problem pojawia się na przykład przy użyciu array_push lub implode itp
Dla implode można stosować rzutowanie, np. implode( ',', (array) $oArray->test)
Go to the top of the page
+Quote Post
Jarod
post 4.12.2006, 18:08:25
Post #10





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Cytat(cassis @ 4.12.2006, 08:33:00 ) *
[php]<?php
$oArray->test = new ArrayObject();


Przecież obiekt ArrayTest nie posiada atrybutu test .. dry.gif Powinno wywalić błąd a nie wywala..


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
cassis
post 4.12.2006, 18:14:42
Post #11





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 4.12.2006

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


Do tego właśnie służą magiczne metody __get() __set() __call() - jak czegoś nie ma to one się tym zajmują
Manual
Go to the top of the page
+Quote Post
Jarod
post 4.12.2006, 19:28:34
Post #12





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Tylko jaki jest sens przypisywać nieistniejącej zmiennej wartość? Lepiej ją najpierw zadeklarować.. Przez to kod dla kogoś innego staje się mniej zrozumiały.


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
cassis
post 4.12.2006, 20:57:58
Post #13





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 4.12.2006

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


maly przyklad
przed uzyciem skontaktuj sie z baza dany i przeczytaj SQLowa ulotke nizej

  1. <?php
  2. class Cars {
  3. protected $items;
  4.  
  5. public function __get( $model) {
  6. if ($this->items === null) {
  7. $query = 'SELECT * FROM cars';
  8. $result = mysql_query( $query);
  9. while ($row = mysql_fetch_assoc( $result)) {
  10. $this->items[$row['model']] = $row['description'];
  11. }
  12. }
  13. if (false == isset( $this->items[$model])) {
  14. throw new Exception( 'nie ma takiej pozycji');
  15. }
  16. return( $this->items[$model]);
  17. }
  18.  
  19. public function __set( $model, $description) {
  20. try {
  21. $this->__get( $model);
  22. $query = 'UPDATE cars SET description=''.$description.'' WHERE model=''.$model.''';
  23. mysql_query( $query);
  24. } catch( Exception $e) {
  25. $query = 'INSERT INTO cars (model, description) VALUES (''.$model.'', ''.$description.'')';
  26. mysql_query( $query);
  27. }
  28. $this->items[$model] = $description;
  29. }
  30. }
  31.  
  32. $cars = new Cars();
  33. $cars->skarpeta = 'fajne auto';
  34.  
  35. try {
  36. echo $cars->skarpeta;
  37. } catch (Exception $e) {
  38. echo $e;
  39. }
  40. ?>


  1. CREATE TABLE `cars` (
  2. `model` varchar(255) NOT NULL,
  3. `description` text NOT NULL,
  4. PRIMARY KEY (`model`)
  5. )


Oczywiscie mozna to usprawniac na wiele sposobow. Zastosowania __get() __set() sa bardzo przydatne.
Zauwaz ze tutaj moznaby zamiast rzucac wyjatek w przypadku braku rekordu zwrocic jakas domyslna wartosc. Wedlug mnie dzieki tego typu rozwiazaniom kod staje sie abrdziej przejrzysty i elegancki. Nieco ciezej sie wykrywa bledy ale mozna zrobic rzeczy bardziej uniwersalne, elastyczne i wielokrotnie wykorzystywac aaevil.gif . Moznaby do tej klasy dodac licznik zapytan i mase innych gadzetow...
Mam nadzieje ze przekonalem nieco...
Pisane na szybko wiec wybaczcie jakies bledy...
Go to the top of the page
+Quote Post
Athlan
post 5.12.2006, 14:38:13
Post #14





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

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


Panowie, panowie smile.gif

Chyba zupełnie odbiegliście od tematu. @cassis już kompletnie nie czai blusa. Chodzi o tworzenie elementów tablicowych z __set() i wkładanie ich do tablicy jako atrybut klasy prawda? Bo co przyjmie pierwszy parametr metody magicznej __set() przy podaniu $oObject->element[] = 'value'; ?

Takie coś: $this->_aAttributes[$sName] - przekształci się w : $this->_aAttributes[element[]] a nie $this->_aAttributes[element][] :!:

Nie czujecie fazy czy udajecie? tongue.gif Temat jest imho EOT. Problem wyjaśniony, możnaby podyskutować o tym, dlaczego przechodziło to w wersjach starszych niż php 5.2.0 ? hę?

Pozdrawiam, Athlan.

Ten post edytował Athlan 5.12.2006, 14:38:47


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
cassis
post 5.12.2006, 16:20:24
Post #15





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 4.12.2006

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


no tak - troche poplynalem. Chcialem wytlumaczyc jedynie o co chodzi z __get i __set...

Wracajac do glownego tematu na liscie bugow php jest taki temat 39449 ze statusem Open. Ktos tam tlumaczy ze to jest prawidlowe zachowanie...

Nie wiem czy to bug czy nie ale nie ladnie ze to zmieniono. Ja poradzilem sobie z tym zmieniajac wszedzie gdzie to potrzebne zwykle tablice na ArrayObject. Do tego zrobilem sobie klase rozszerzajaca i dodalem kilka usprawnien...

Na tym przykladzie widac ze warto sobie wszystko obudowac ladnie tak ze jak sie pojawi nowy "feature" to latwo bedzie to mozna dostosowac...
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 Wersja Lo-Fi Aktualny czas: 19.07.2025 - 00:44