[oop] Serializable
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:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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());
?>
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:
Als ik nu de Serializable interface niet implement, en ik de "serialize" en "unserialize" methods verwijder, krijg je dit:
Code (php)
Het resultaat op mijn scherm is:
Code (php)
1
2
2
string(53) "O:3:"obj":1:{s:9:"objdata";s:15:"My private data";}"
string(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
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
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?
Code (php)
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 :-)
Stel ik heb een class waarin ik een property $data en $locked heb staan.
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?
Gewijzigd op 26/04/2014 22:12:02 door Frank Nietbelangrijk
Oké, dankje. Dan haal ik het hier maar weg aangezien het niks toevoegt.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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;
?>
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:
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.
Heeft het dan ook zin om serialize en unserialize te gebruiken? In jouw voorbeeld gaat het om 2 strings en dan begrijp ik wat je bedoelt. Maar hier gaat het om een array ($data). Kun je dan ook zo'n truc doen, of voegt het niks toe?
Code (php)
1
2
2
O:3:"Foo":2:{s:9:"?Foo?data";a:2:{i:0;s:3:"foo";i:1;s:3:"fiz";}s:11:"?Foo?locked";b:0;}
C:3:"Foo":37:{a:2:{i:0;s:3:"foo";i:1;s:3:"fiz";}||0}
C:3:"Foo":37:{a:2:{i:0;s:3:"foo";i:1;s:3:"fiz";}||0}
Eerste is zoals jij het nu hebt, tweede is met:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class Foo implements Serializable {
private $data = array('foo', 'fiz');
private $locked = false;
public function serialize()
{
return serialize($this->data).'||'.($this->locked ? 1 : 0);
}
public function unserialize($serialized)
{
list($data, $locked) = explode('||', $serialized, 2);
$this->data = unserialize($data);
$this->locked = (boolean) $locked;
}
}
?>
class Foo implements Serializable {
private $data = array('foo', 'fiz');
private $locked = false;
public function serialize()
{
return serialize($this->data).'||'.($this->locked ? 1 : 0);
}
public function unserialize($serialized)
{
list($data, $locked) = explode('||', $serialized, 2);
$this->data = unserialize($data);
$this->locked = (boolean) $locked;
}
}
?>
Begrijp ik dus goed dat je zo'n constructie vooral gebruikt om ruimte te besparen?
Waarom kies je in je 1e voorbeeld voor %$% als scheidingsteken, en in je 2e voorbeeld voor || ?
Dat is inderdaad wel 1 van de hoofdfeiten voor het gebruik van Serializable. Ruimte en bepalen welke properties elke keer opnieuw moeten geset worden en dus niet gecached of welke properties er wel verstuurd mogen worden naar een 3rd party.
>> Waarom kies je in je 1e voorbeeld voor %$% als scheidingsteken, en in je 2e voorbeeld voor || ?
Beetje willekeurig. Je moet een teken bedenken die niet snel gebruikt kan worden in de properties die je hebt. Iets als %$% zal je niet vaak tegenkomen.
Allright. Ik ga er eens wat mee spelen ;)