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.
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?
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.
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?
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
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);
}
}