• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Bestehendes in Session gespeichertes Objekt mit Methode verändern

Steini1980

New member
Hallo,
ich bin gerade dabei einen Warenkorb aus einem bestehenden Shop zu verbessern, alle Artikel im Warenkorb sollen als Objekt "artikel" gespeichert werden. Wenn ein Artikel bereits vorhanden ist, soll der Bestand angepasst werden können. Dafür wollte ich die Methode addMenge() verwenden, doch leider funktioniert das irgendwie nicht.

Ich beschäftige mich erst seit kurzem so richtig intensiv mit OOP, aber wenn ich das richtig nachvollziehe speichert er das Artikel-Objekt doch als Array in meiner Session-Variable ab. Hab ich dann wenn ich später auf das Objekt in der Session zugreife überhaupt noch Zugriff auf meine Methoden von Artikel oder kann ich hier nur noch die Eigenschaften direkt ändern?

PHP:
class warenkorb {

  var $artikel = array();
  
  public function nimmArtikeldazu($artikel_id, $anz = 0) {
    if (isset($this->artikel[$artikel_id])) {
      $this->artikel[$artikel_id]->addMenge($anz);
    } else {
      $this->artikel[$artikel_id] = new artikel($artikel_id, $anz);
    }
  }
}

PHP:
class artikel {
  var $menge;
  var $artikel_id;
  var $varianten_id;
  var $artikel_nr;
  var $artikel_name;
  var $artikel_preis;
  
  // Konstruktor:
  public function __construct($id, $menge = 1) {
    if(!isset($id)) { return false; }
    $this->menge = $menge;
    $this->artikel_id = $id;
  }
  
  /* ... Setter/Getter-Methoden usw. */

  // Fügt die Menge zum Objekt hinzu:
  public function addMenge($menge) {
    if(!is_int($menge)) { return false; }
    $this->menge += $menge;
  }
}
 
Vielen Dank für den wertvollen Tipp.. Wusste doch, dass irgendetwas noch fehlen muss damit ich Zugriff aufs Objekt habe.

Habe das jetzt wie folgt geändert, alte Version:
PHP:
if (!isset($_SESSION["basket"])) {
    $basket = &new warenkorb;
} else {
      $basket = $_SESSION["basket"];
} 

 /* ... usw. ... */

$_SESSION["basket"] = $basket;

Neue Version:
PHP:
if (!isset($_SESSION["basket"])) {
    $basket = new warenkorb;
} else {
      $basket = unserialize($_SESSION["basket"]);
} 

 /* ... usw. ... */

$_SESSION["basket"] = serialize($basket);

Früher konnte ich mit print_r($basket) das Objekt als Array anzeigen lassen, seit der Änderung bekomme ich als Ergebnis einen serialisierten String zurück:

Code:
O:9:"warenkorb":1:{s:7:"artikel";a:1:{s:13:"34830::396435";O:7:"artikel":6:{s:5:"menge";s:1:"1";s:10:"artikel_id";s:13:"34830::396435";s:12:"varianten_id";N;s:10:"artikel_nr";N;s:12:"artikel_name";N;s:13:"artikel_preis";N;}}}

Also irgendwas schein noch nicht ganz zu passen. Serialize funktioniert zwar, aber mein unserialize Streikt. Kann das evtl. daran liegen, dass sich innerhalb meines Objekts Warenkorb ein Array mit weiteren Objekten vom Typ Artikel befindet?

Hier die vorherige Ausgabe:
Code:
warenkorb Object ( [artikel] => Array ( [34830::396435] => artikel Object ( [menge] => 1 [artikel_id] => 34830::396435 [varianten_id] => [artikel_nr] => [artikel_name] => [artikel_preis] => ) ) )

Muss ich da etwa jedes einzelne Unterobjekt nochmals unserialisieren?
 
Zuletzt bearbeitet:
sieht für mich eher so aus als würdest du vergessen den basked zu unserialisieren.
Ob es Probleme macht dass das Objekt selbst weitere Objekte als Eigenschaft hat weiß ich spontan nicht, würde aber mal "nein" tippen.
Du kannst ja mal probieren diese unterobjekte selbst noch mal zu (un)serialisieren:
PHP:
class warenkorb {
    var $artikel = array();

    public function nimmArtikeldazu($artikel_id, $anz = 0) {
        if (isset($this->artikel[$artikel_id])) {
            $this->artikel[$artikel_id]->addMenge($anz);
        } else {
            $this->artikel[$artikel_id] = new artikel($artikel_id, $anz);
        }
    }

    public function __sleep() {
        foreach($this->artikel AS $id => $obj) {
            $this->artikel[$id] = serialize($obj);
        }
    }

    public function __wakeup() {
        foreach($this->artikel AS $id => $obj) {
            $this->artikel[$id] = unserialize($obj);
        }
    }
}
 
Mit den Sleep und Wakeup Methoden bekomm ich leider eine Fehlermeldung:

Fatal error: Call to a member function nimmArtikeldazu() on a non-object in ...datei.php on line 30

Allerdings funktioniert ja die bisherige Variante mit Serialize und Unserialize insoweit, dass alle Methoden und Eigenschaften von Warenkorb wiederhergestellt werden. Von Artikel werden jedoch nur die Eigenschaften nach dem Unserialize wiederhergestellt und ich habe keinen Zugriff mehr auf die Methoden von Artikel.

Vielleicht gibts da irgendeinen Eleganteren Weg, so dass die Methoden von Artikel weiterhin zur Verfügung stehen. Ich werde jetzt dennoch versuchen basierend auf deinem Ansatz irgendwie das Array der Artikel-Objekte korrekt Unzuserialisieren.
 
Allerdings funktioniert ja die bisherige Variante mit Serialize und Unserialize insoweit, dass alle Methoden und Eigenschaften von Warenkorb wiederhergestellt werden. Von Artikel werden jedoch nur die Eigenschaften nach dem Unserialize wiederhergestellt und ich habe keinen Zugriff mehr auf die Methoden von Artikel.

Wenn das so ist klingt es sehr danach als müsse man das manuell (über sleep und wakeup) (un)serialisieren, poste mal den code der deiner meinung nach fehler produziert - was passiert da z.b. auf zeile 30?
 
Hab die Lösung, nochmals 1000 Dank für deine Hilfe.

Die __Sleep-Funktion erfordert einen Rückgabewert:
PHP:
    public function __sleep() {
        foreach($this->artikel AS $id => $obj) {
            $this->artikel[$id] = serialize($obj);
        }
       return array('artikel');
    }

Siehe auch php.net:
serialize() checks if your class has a function with the magic name __sleep. If so, that function is being run prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. If the method doesn't return anything then NULL is serialized and E_NOTICE is issued.
 
Zurück
Oben