Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Problem z serializacją obiektu
vegelus
post
Post #1





Grupa: Zarejestrowani
Postów: 25
Pomógł: 0
Dołączył: 31.05.2005

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


Witam

Mam problem z serializacją obiektu posiadającego inne obiekty. Może przykład coś wyjaśni:
  1. class Map{
  2. private $wys;
  3. private $sze;
  4. private $map = array();
  5.  
  6. function __construct($wys,$sze){
  7. $this->wys = $wys;
  8. $this->sze = $sze;
  9. //przypisanie w map do każdego pola klasy obiektu z klasy field
  10. for ($x = 1; $x <= $this->sze; $x++) {
  11. for ($y = $this->wys; $y >= 1; $y--) {
  12. $losowa = rand(1, 4);
  13. $picPath = 'flor' . $losowa . '.png';
  14. $this->map[$y][$x] = new field($picPath);//obiekt nic nie robi poza przechowywaniem patha do obrazka i contentu pola
  15. }
  16. }
  17. }
  18.  
  19. function __sleep(){
  20. for ($x = 1; $x <= $this->sze; $x++) {
  21. for ($y = $this->wys; $y >= 1; $y--) {
  22. $_SESSION['maps'][$y][$x] = serialize($this->map[$y][$x]);
  23. }
  24. }
  25. return array('sze', 'wys');//chcę serializować tylko te dwa atrybuty
  26. }
  27. }


Efekt serializacji poszczególnych pól tablicy map jest prawidłowy ale w przypadku serializacji obiektu map :
  1. if (!isset($_SESSION['map'])) {
  2. $map = new map(4, 4);
  3. $_SESSION['map'] = serialize($map);
  4. } else {
  5. $map = unserialize($_SESSION['map']);
  6. }



Serializacji usilnie ładuje do sesji wszystko z obiektu łącznie atrybutem map, który już wcześniej sobie do sesji zapisałem i w __wakeup pobrałem z powrotem.

Jak zrobić aby serializując obiekt zapisać sobie proste zmienne a pozostałe serializować ręcznie.
A może jest jakiś inny lepszy sposób radzenia sobie z obiektami zawierającymi inne obiekty?


ps. poprawiłem (IMG:style_emoticons/default/smile.gif) pisałem z ręki gdyż klasa zainteresowana serializacją ma już ponad 1000 linii i nie widziałem sensu jej tu całej pchać. Jest to wycinek tej klasy generujący moją frustrację oraz błąd.

Ten post edytował vegelus 24.03.2010, 14:34:13
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 4)
ziqzaq
post
Post #2





Grupa: Zarejestrowani
Postów: 428
Pomógł: 128
Dołączył: 17.06.2007

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


Aleś sobie namieszał (IMG:style_emoticons/default/smile.gif)
  1. // Najpierw
  2. $this->wys = $wys;
  3. $this->sze = $sze;
  4. // a potem
  5. for ($x = 1; $x <= $this->width; $x++) {
  6. for ($y = $this->height; $y >= 1; $y--) {
  7. // i jeszcze chcesz serializowac
  8. return array('width', 'height');

no i jeszcze:
  1. //...
  2. funtion __sleep(){
  3. //...
Go to the top of the page
+Quote Post
zend
post
Post #3





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

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


Cytat(vegelus @ 24.03.2010, 12:51:58 ) *
1.
if (!isset($_SESSION['map'])) {
2.
$map = new map(4, 4);
3.
$_SESSION['map'] = serialize($map);
4.
} else {
5.
$map = unserialize($_SESSION['map']);
6.
}


Takiego mixu to ja już dawno nie widziałem (IMG:style_emoticons/default/smile.gif) Tworzysz obiekt a potem odrazu go serializujesz, nie wykonując na nim żadnych operacji (IMG:style_emoticons/default/smile.gif)
To może ci się wydawać dobre i działać, ale świadczy tylko o złym zaprojektowaniu klasy. Zastanów się czy tych 1000 lini kodu nie da się rozłożyć do kilku klas, bo takie giganty strasznie zalatują "god's class", a z tąd już tylko krok do programowania strukturalnego.

Edit:
A poza tym staraj się utrzymywać jakąć stałą konwencję co do nazewnictwa, a nie mieszaj polskiego z angielskim, albo rybki albo akwarium (IMG:style_emoticons/default/smile.gif)

A teraz będzie troche na temat (IMG:style_emoticons/default/smile.gif) A że poźno jest, a ja zmęczony to będzie to metoda brutal force (IMG:style_emoticons/default/smile.gif)
Po serializacji map chamsko wyczyść to pole unset'em, to dane nie będą się dublować, zakładająć oczywiście że nie masz jakoś dziwnie zaimplementowanych destruktorów w fildzie

A teraz dobranoc, koniec imprezy (IMG:style_emoticons/default/smile.gif) Ide spać

Ten post edytował zend 25.03.2010, 23:26:36
Go to the top of the page
+Quote Post
vegelus
post
Post #4





Grupa: Zarejestrowani
Postów: 25
Pomógł: 0
Dołączył: 31.05.2005

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


Dzięki za odpowiedz.

Jeszcze są dwie linijki kodu w index.php
  1. session_start();
  2.  
  3. if (!isset($_SESSION['map'])) {
  4. $map = new map(4, 4);
  5. $map->setHero(new Hero(2,1));
  6. } else {
  7. echo 'unserialize MAP<br>';
  8. $map = unserialize($_SESSION['map']);
  9. }
  10.  
  11. if (!empty($_GET['move'])) {
  12. $map->moveHero($_GET['move']);
  13. }
  14.  
  15. ?>
  16.  
  17. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  18. <html>
  19. <head>
  20. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  21. <link rel="Stylesheet" type="text/css" href="style.css" />
  22. <title>Plansza gry</title>
  23. </head>
  24. <body>
  25. <div id="kontener">
  26. <div id="map"><?=$map->paint(); ?></div>
  27. <div id="control"><?=control::paint(); ?></div>
  28. </div>
  29. <div><?php Komunikaty::getKomunikaty();?></div>
  30.  
  31.  
  32. </body>
  33. </html>
  34. <?php
  35. if (!isset($_SESSION['map'])) {
  36. $_SESSION['map'] = serialize($map);
  37. }


Na twoje rozwiązanie także wpadłem i zrobiłem sobie taką funkcję __sleep
  1. public function __sleep() {
  2. $_SESSION['hero'] = serialize($this->hero);
  3. for ($x = 1; $x <= $this->width; $x++) {
  4. for ($y = $this->height; $y >= 1; $y--) {
  5. $_SESSION['maps'][$y][$x] = serialize($this->map[$y][$x]);
  6. }
  7. }
  8. unset($this->hero);
  9. unset($this->map);
  10. return array('width', 'height', 'map', 'hero');
  11. }


Myślałem jednak, że istnieje jakiś ładniejszy sposób serializacji obiektów kontenerowych.
Dla potomnych może jeszcze podam jak budzę obiekt do życia pozostawiając oryginalne nazewnictwo:
  1. public function __wakeup() {
  2. $this->hero = unserialize($_SESSION['hero']);
  3. for ($x = 1; $x <= $this->width; $x++) {
  4. for ($y = $this->height; $y >= 1; $y--) {
  5. $this->map[$y][$x] = unserialize($_SESSION['maps'][$y][$x]);
  6. }
  7. }
  8. }


Udało mi się w końcu upchnąć obiekt w sesji (IMG:style_emoticons/default/smile.gif)
Najwięcej czasu zajęło mi osiągnięcie tego efektu:
  1. [map] => O:3:"map":4:{s:10:"mapwidth";i:4;s:11:"mapheight";i:4;s:8:"mapmap";N;s:9:"maphero";N;}


Serializacjia przy pierwszym odpaleniu strony jest idealna, wszystkie obiekty wewnętrzne są w sesji i po deserializacji się odtwarzają, więc można powiedzieć, że osiągnąłem jakiś sukces. Ale po wykonaniu działań i przeładowaniu strony pojawia się problem, którym już nie wiem jak sobie poradzić. Mianowicie przy drugiej serializacji do zmiennej $_SESSION ładuje mi się coś takiego:

  1. [map] => map Object
  2. (
  3. [hero:private] => Hero Object
  4. (
  5. [actionPoint:private] => 29
  6. [posX:private] => 2
  7. [posY:private] => 2
  8. )
  9.  
  10. [width:private] => 4
  11. [height:private] => 4
  12. [map:private] => Array
  13. (
  14. [4] => Array
  15. (
  16. [1] => field Object
  17. (
  18. [picPath:private] => flor2.png
  19. [content:private] =>
  20. )
  21.  
  22. ...
  23.  


czyli obiekty hero i map nie zostały zniszczone i przekazane do serializacji jako obiekty anie NULL, co powoduje błąd przy deserializacji
Warning: unserialize() expects parameter 1 to be string, object given in D:\WebServ\httpd-users\pole_gry\index.php on line 8

Ten post edytował vegelus 26.03.2010, 00:45:34
Go to the top of the page
+Quote Post
zend
post
Post #5





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

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


Pokręć się koło tematu session_register, bo wygląda na to że obiekt w sesji jest automatycznie deserializowany, a funkcja unserialize przyjmuje stringi a nie już odserializowane obiekty (IMG:style_emoticons/default/smile.gif) Wszystko działa ok, wygląda na to że brakowało Ci tego klocka o automatycznej deserializacji (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post

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: 9.10.2025 - 04:08