Hallo guys,

Ik werd vandaag getipt over de Serializable interface, dat die handig zou zijn als je objecten gaat cachen.

Op php.net zie ik dit voorbeeld:

<?php

class obj implements Serializable {
private $data;
public function __construct() {
$this->data = "My private data";
}
public function serialize() {
return serialize($this->data);
}
public function unserialize($data) {
$this->data = unserialize($data);
}
public function getData() {
return $this->data;
}
}

$obj = new obj;
$ser = serialize($obj);

var_dump($ser);

$newobj = unserialize($ser);

var_dump($newobj->getData());

?>
Het resultaat op mijn scherm is:


string(38) "C:3:"obj":23:{s:15:"My private data";}"
string(15) "My private data"


Als ik nu de Serializable interface niet implement, en ik de "serialize" en "unserialize" methods verwijder, krijg je dit:

<?php

class obj {
private $data;
public function __construct() {
$this->data = "My private data";
}

public function getData() {
return $this->data;
}
}

$obj = new obj;
$ser = serialize($obj);

var_dump($ser);

$newobj = unserialize($ser);

var_dump($newobj->getData());

?>
Het resultaat op mijn scherm is:


string(53) "O:3:"obj":1:{s:9:"objdata";s:15:"My private data";}"
string(15) "My private data"

Wat is nu eigenlijk het verschil? Ik zie wel dat de 1e regel op mijn scherm korter is in het 1e voorbeeld dan in het 2e voorbeeld.
http://3v4l.org/alrdB

O:3:"obj":1:{s:9:"objdata";s:15:"My private data";}
O staat voor object (niet de unserialize() methode aanroepen)
3 strlen('obj')
"obj" de naam van de class
1 aantal variabelen
{ begin van de data
s string
9 strlen('objdata')
"objdata" private (kun je herkennen door de class naam prefix) $data
; einde waarde
s string
15 strlen('My private data')
"My private data" waarde voor private $data
; einde waarde
} einde data


C:3:"obj":23:{s:15:"My private data";}
C staat voor class (roep de unserialize() methode aan)
3 strlen('obj')
"obj" class naam
23 strlen('s:15:"My private data";')
{ begin data
s string
15 strlen('My private data')
"My private data" de waarde die aan unserialize wordt gegeven
; einde waarde
} einde data
Thanks Dos! Mooie uitleg.

Om de verschillen nu te begrijpen... met de serialize methode geef je aan welke data (uit de properties) moet worden opgeslagen, en via unserialize geef je aan waar die data heen moet. Zou je het zo kunnen zeggen? En wat is nu precies het nut? Dat het geserializede object in de laatste versie minder ruimte inneemt?
Dat niet alles geserialiseert hoeft te worden. De database verbinding zou je lekker kunnen laten zitten als je deze via een statische methode op kan vragen bijvoorbeeld.

<?php

class miauw implements Serializable {

public function serialize() {
return $alles_behalve_database_verbinding;
}

public function unserialize($data) {
$this->connection = Database::getConnection();

//...
}
}

?>

Je hebt controle over wat er in een bestand/database/sessie/cookie/whatever dat door weet ik veel wie gelezen kan worden komt te staan.
Ah zo, oke... thanks Dos. Ik leer steeds meer :-)
Nog even een vraagje over serializable.

Stel ik heb een class waarin ik een property $data en $locked heb staan.

<?php
class Foo {

private $data;
private $locked = false;

}
?>
Als ik nu telkens wanneer ik het object serialize deze 2 properties wil opslaan, hebben de serialize en unserialize methods dan nog enige toegevoegde waarde? Of kan ik die 2 methods en de interface beter achterwege laten?
Het lijkt me dan makkelijker om deze achterwege te laten aangezien je het hele object dan wilt serializen.
Oké, dat lijkt mij inderdaad ook. Maar wanneer gebruik je de Serializable interface dan in de praktijk? Ik zou denken dat je die niet zo heel vaak nodig hebt eigenlijk?
Zoals Dos zegt: Enkel wanneer je niet alles uit een object wilt serializen of als je misschien je data enigzins wilt wijzigen bij het serializen/unserializen
Oké, dankje. Dan haal ik het hier maar weg aangezien het niks toevoegt.
Er is wel een groot verschil: Met serializable bepaal je hoe je een object serialized. Zonder het wordt het complete object geserialized. Dit kan voor behoorlijk wat ruimtebesparing zorgen:
<?php
class A
{
public $b = 'foo';
public $c = 'fiz';
}

class B extends A implements Serializable
{
public function serialize()
{
return $this->b.'%$%'.$this->c;
}

public function unserialize($data)
{
list($this->b, $this->c) = explode('%$%', $data, 2);
}
}

$a1 = new A();

$b = new B();

echo 'A: ', serialize($a1), PHP_EOL;
echo 'B: ', serialize($b), PHP_EOL;
?>
Resultaat:

A: O:1:"A":2:{s:1:"b";s:3:"foo";s:1:"c";s:3:"fiz";}
B: C:1:"B":9:{foo%$%fiz}

Zoals je ziet wordt bij A een object (O:) genaamd A geserialized, waarvan de property b een waarde "foo" heeft en "c" de waarde "fiz".

Bij B wordt geen object, maar een klasse (C:) genaamd B geserialized, hiervan wordt daarnaast de return waarde van serialize geplakt.

In dit geval zijn het 2 simpele objecten die ik doormiddel van de %$% symbool van elkaar scheid.

Reageren