serialisierte klasseninstanz einlesen
frankx
- php
Hellihello
mit
class Record {
var $feld1="feld1";
private $feld2="feld2";
function __construct () {
}
function setFeld2($wert) {
$this->feld2=$wert;
}
function write($name) {
file_put_contents($name, serialize($this));
}
function read($name) {
return unserialize(file_get_contents($name));
}
function load($name) {
$dateiInhalt=new Record;
$dateiInhalt=unserialize(file_get_contents($name));
foreach ($dateiInhalt as $key => $value) {
$this->$key=$value;
}
// geht nicht: $this=$dateiInhalt;
}
}
$record = new Record;
$record->setFeld2("feld2 neuer wert");
$record->write("dateiname");
$record1=new Record;
// geht aber unschön, weil nicht in Funktion verpackt
$dateiInhalt=unserialize(file_get_contents("dateiname"));
$record1=$dateiInhalt;
var_dump($record1);
$record2=new Record;
//geht auch, sieht aber irgendwie doppeltgemoppelt aus
$record2=$record2->read("dateiname");
var_dump($record2);
// ist das optimal?
$record3=new Record;
$record3->load("dateiname");
var_dump($record3);
habe ich drei Möglichkeiten durchprobiert, den Inhalt einer Klasseninstanz aus einem serialisierten Datenfile auszulesen. Mein geträumter Favorit ist oben in der Funktion load auskommentiert und geht nicht, denn $this=$datenSatz gibt "Fatal error: Cannot re-assign $this...".
Ist o.g. function load dann die "einfachste/beste/galanteste" Lösung oder ist mir ein Ansatz bisher entgangen?
dank und gruß
frankx
Hi,
Ist o.g. function load dann die "einfachste/beste/galanteste" Lösung oder ist mir ein Ansatz bisher entgangen?
In folgendem Beispiel wird der Variablen $c durch unserialize() bereits ein Objekt zugewiesen.
Habe es unter PHP4.4.0 und PHP 5.0.5 getestet (In PHP5 müsste var
eigtl. noch spezifiziert werden).
<?
class test
{
var $toast = 'teaser!';
function toast()
{
echo $this->toast;
}
}
$a = new test;
$b = serialize($a);
$c = unserialize($b);
$c->toast();
?>
Einzige Voraussetzung dafür ist, wie im Manual steht, dass die Klasse vor Aufruf von unserialize definiert wurde.
Daher brauchst du gar keine eigene load-Methode bzw. -Funktion; du kannst deine erste Lösung einfach entsprechend abkürzen:
$record1 = unserialize(file_get_contents("dateiname"));
Freundliche Grüße,
Sancho
Hellihello Sancho,
besten Dank für die Antwort.
So wie Du schreibst, bzw. mit einer Zischenvariablen mehr, steht es ja schon im Code.
$record1=new Record;
// geht aber unschön, weil nicht in Funktion verpackt
$dateiInhalt=unserialize(file_get_contents("dateiname"));
$record1=$dateiInhalt;
Also erst eine Instanz des Objektes erstellen, dann dieser den Datensatz zuordnen.
Irgendwie dachte ich aber es wäre am objektgemäßesten, dass in einer Methode des Objektes unterzubring, mit der es sich selbst mit Daten lädt. Aber das scheitert dann ja daran, dass $this nicht re-assigned werden darf, was dann zur Folge hätte, dass eine eigentlich unnötige foreach-Schleife benutzt werden müsste.
Dank und Gruß, frankx
Hellihello
public static function load1($name) {
$dateiInhalt=new Record;
$dateiInhalt=unserialize(file_get_contents($name));
return $dateiInhalt;
}
mit
$record=Record::laod1("dateiname");
scheint mir o.k.
frankx
Hi,
public static function load1($name) {
$dateiInhalt=new Record;
$dateiInhalt=unserialize(file_get_contents($name));
return $dateiInhalt;
}
>
> mit
>
> ~~~php
> $record=Record::laod1("dateiname");
>
scheint mir o.k.
Naja, ist immer noch etwas viel Aufwand - denn genau den gleichen Effekt hätte ja ein schlichtes:
$record = unserialize(file_get_contents("dateiname"));
Sinnvoller wäre, das Ergebnis der Dateioperation vorher noch zu prüfen, also in PHP 5 etwa:
$path = '/tmp/xyz';
if ($s = file_get_contents($path))
{
$myObj = unserialize($s);
} else {
throw new Exception("Error reading $path");
}
Beim Laden eines Objekts über unserialize() musst du allerdings beachten, dass _bestimmte_ Objekteigenschaften anschließend in jedem Fall gesondert wiederhergestellt werden müssen: Ressourcen-Handles und Referenzen. Wenn in einer Objekteigenschaft z.B. eine MySQL-Verbindungskennung gespeichert ist, dann geht diese über serialize/unserialize verloren.
PHP 5 bietet hierfür die abstrakte 'magische Methode' __wakeup(), die automatisch nach einer Objektwiederherstellung über unserialize aufgerufen wird. (Über __sleep() kann zudem festgelegt werden, welche Objekteigenschaften überhaupt serialisiert werden sollen.)
In PHP 4 muss zusätzlich zur Methode auch ihr Aufruf jeweils selbst implementiert werden.
Freundliche Grüße,
Sancho
echo $begrüßung;
$dateiInhalt=new Record;
$dateiInhalt=unserialize(file_get_contents($name));
Das Instantiieren vor dem Unserialisieren ist im Prinzip nicht erforderlich. unserialize() erzeugt Instanzen für die zu unserialisierenden Werte von selbst. Allerdings ruft es dabei nicht noch einmal den Konstruktor auf. Falls der Konstruktor irgendwelche Nebeneffekte auf Teile außerhalb des Objekts hat, müsste man ihn so wie oben aufrufen, aber guter Stil wäre das nicht.
echo "$verabschiedung $name";
Hallo dedlfix,
sehe gerade, dass ich dich versehentlich gleich doppelt übergangen habe: dein obiges Posting hatte ich noch nicht gelesen, als ich dieses zusätzlich noch abschickte; und der darin enthaltenen Link führt jetzt glatt an deinem Posting vorbei.
Muss mir einfach angewöhnen, vor dem Absenden immer noch mal in den Threadverlauf zu schauen... perdon.
Freundliche Grüße,
San*der_zerstreute*cho
Hi,
Also erst eine Instanz des Objektes erstellen, dann dieser den Datensatz zuordnen.
Wie gesagt, unserialize() liefert dir, sofern eine entsprechende Klassendefinition vorhanden ist, bereits eine Objektinstanz. Die von dir zuvor erstellte wird dann einfach durch die neue ersetzt, hätte also gar nicht erst erstellt werden müssen ;)
Weiteres hier.
Freundliche Grüße,
Sancho