[oop] object cachen?
Stel we hebben een object (bijv. een service container) en bij ieder request moet dat gevuld worden met dezelfde initiële data. Schematisch krijg je dan zoiets:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$config_file = yaml_parse_file('/pad/naar/configbestand.yml');
$container = new Container();
$container->loadArgs($config_file['args']);
$container->loadServ($config_file['serv']);
?>
$config_file = yaml_parse_file('/pad/naar/configbestand.yml');
$container = new Container();
$container->loadArgs($config_file['args']);
$container->loadServ($config_file['serv']);
?>
Is het nu mogelijk om als deze handelingen zijn gedaan het object te cachen in een cache bestand? En als dan de volgende keer de pagina wordt aangeroepen er gekeken wordt of er een cache bestand aanwezig is, en zo ja dan gebruik ik de gecachete versie en hoeven alle bovengenoemde stappen niet meer te worden uitgevoerd?
Kan dat, en zo ja hoe?
Gewijzigd op 20/04/2013 16:09:44 door Ozzie PHP
memcached kunnen overwegen.
Je zou Nou, ik wil eigenlijk gewoon zelf iets maken. Maar de vraag is eigenlijk het mogelijk is wat ik wil.
1) Gebruik gewoon serialize en deserialize
2) Maak __sleep en __wakeup methods of gebruik de serializable interface. Hiermee hoef je dus niet de hele class te cachen, maar alleen de variabele data (bijv. de property die alle services en parameters vasthoudt)
3) Gebruik een library als JmsSerializer. Op die manier kun je heel goed bepalen wat je wel en niet gaat serializen, op welke manier en in welke taal (yaml, xml, json, ect.)
Thanks voor je reactie.
Mijn voorkeur gaat dan uit naar optie 1 of 2. Slaat optie 1 ook alle properties op? En kun je dan gewoon zeggen:
$container = unserialize(file_get_contents('/pad/naar/gecachteversie'));
Wat bedoel je bij optie 2 met "Hiermee hoef je dus niet de hele class te cachen..."?
Bedoel je dat bij optie 1 ook alle methods worden gecachet? In dat geval is optie 2 wellicht handiger en dat ik dan alleen de properties cache... heb je wellicht een heel simpel voorbeeldje voor me hoe optie 2 in z'n werk gaat? De bedoeling is dus dat ik niet telkens alle configuratie hoef in te lezen en te setten, maar dat ik direct een gecachet object terugkrijg. Ik hoop dat het een beetje duidelijk is wat ik bedoel.
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
29
30
31
32
33
34
35
36
37
38
39
40
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
29
30
31
32
33
34
35
36
37
38
39
40
<?php
class Container implements \Serializable
{
private $services;
private $parameters;
public function set($id, $factory)
{ ... }
public function get($id)
{ ... }
// ...
public function serialize()
{
return serialize(array(
'services' => $this->services,
'parameters' => $this->parameters,
));
}
public function unserialize($data)
{
$data = unserialize($data);
$this->services = $data['services'];
$this->parameters = $data['parameters'];
}
}
// first time
$container = new Container();
// ... configure the container
file_set_contents(__DIR__.'/cache/di/container.php.inc', serialize($container));
// next time
$container = unserialize(file_get_contents(__DIR__.'/cache/di/container.php.inc'));
?>
class Container implements \Serializable
{
private $services;
private $parameters;
public function set($id, $factory)
{ ... }
public function get($id)
{ ... }
// ...
public function serialize()
{
return serialize(array(
'services' => $this->services,
'parameters' => $this->parameters,
));
}
public function unserialize($data)
{
$data = unserialize($data);
$this->services = $data['services'];
$this->parameters = $data['parameters'];
}
}
// first time
$container = new Container();
// ... configure the container
file_set_contents(__DIR__.'/cache/di/container.php.inc', serialize($container));
// next time
$container = unserialize(file_get_contents(__DIR__.'/cache/di/container.php.inc'));
?>
Nu is dit nog lekker simpel, mocht je wat complexere klassen krijgen wordt JmsSerializer erg interessant.
Gewijzigd op 20/04/2013 17:32:08 door Wouter J
De methods serialize en unserialize horen die bij Serializable?
Nu heb jij hier een serialize en unserialize method gebruikt, maar wat gebeurt er als je die niet gebruikt? Wat is het verschil als je die 2 methods zou weglaten? Dus op deze manier:
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
class Container
{
private $services;
private $parameters;
public function set($id, $factory)
{ ... }
public function get($id)
{ ... }
// ...
}
// first time
$container = new Container();
// ... configure the container
file_set_contents(__DIR__.'/cache/di/container.php.inc', serialize($container));
// next time
$container = unserialize(file_get_contents(__DIR__.'/cache/di/container.php.inc'));
?>
class Container
{
private $services;
private $parameters;
public function set($id, $factory)
{ ... }
public function get($id)
{ ... }
// ...
}
// first time
$container = new Container();
// ... configure the container
file_set_contents(__DIR__.'/cache/di/container.php.inc', serialize($container));
// next time
$container = unserialize(file_get_contents(__DIR__.'/cache/di/container.php.inc'));
?>
Offtopic:
Waarom gebruik je als extensie .php.inc ?
Quote:
De methods serialize en unserialize horen die bij Serializable?
Jep
Quote:
Nu heb jij hier een serialize en unserialize method gebruikt, maar wat gebeurt er als je die niet gebruikt? Wat is het verschil als je die 2 methods zou weglaten?
Ga ik een heel gemeen antwoord op geven: Test het eens zelf. Ik zou het echt niet weten. Ik heb zo mijn gevoelens dat de Serializable methods niet voor niks bestaan en dus waarschijnlijk ruimte beperken, maar ik zou het niet durven zeggen.
Quote:
Waarom gebruik je als extensie .php.inc ?
Ik moest even snel een extensie bedenken. php.inc gebruik ik altijd als het een 'niet echt' PHP bestand is. Bijv. een autoload.php.inc bestand waarin alle klassen staan.
Wouter J op 24/04/2013 19:12:03:
Ga ik een heel gemeen antwoord op geven: Test het eens zelf. Ik zou het echt niet weten. Ik heb zo mijn gevoelens dat de Serializable methods niet voor niks bestaan en dus waarschijnlijk ruimte beperken, maar ik zou het niet durven zeggen.
Ik ben inmiddels zover dat ik het daadwerkelijk heb kunnen testen. Die methods heb je niet nodig tenzij je iets specifieks wilt doen op het moment dat het object wordt geserialized of geunserialized. Als je de methods niet gebruikt werkt het prima :)
Code (php)
1
2
2
C:9:"Container":91:{a:2:{s:8:"services";a:1:{s:3:"foo";s:3:"bar";}s:10:"parameters";a:1:{s:3:"baz";s:3:"bar";}}}
O:9:"Container":2:{s:19:"Containerservices";a:1:{s:3:"foo";s:3:"bar";}s:21:"Containerparameters";a:1:{s:3:"baz";s:3:"bar";}}
O:9:"Container":2:{s:19:"Containerservices";a:1:{s:3:"foo";s:3:"bar";}s:21:"Containerparameters";a:1:{s:3:"baz";s:3:"bar";}}
Eerste is met Serializable, 2e zonder. Je ziet dat de 1e alleen een array serialized en de 2e het hele object. De eerste is kleiner, wat bij het cachen van veel klassen dus echt een verschil gaat uitmaken.
Wouter, thanks. Ik zie alleen niet echt (veel) verschil, behalve dat de 2e langer is omdat daar ipv services en parameters Containerservices en Containerparameters staat. Kun je eens uitleggen wat je bedoelt, want ik denk dat ik ergens overheen aan het kijken ben.
Dat betekend dus dat de 2e een instance vasthoud en de 1e alleen maar een classname.
Dan gaan we verder en krijgen we de lengte van de classname en de classname zelf. Vervolgens krijgen we de properties. Hierin zien we dat in het 1e geval een array met 2 elementen± services en parameters wordt opgeslagen. In het 2e geval worden er 4 dingen op geslagen: een string met de property naam en zijn value en dat 2 keer.
In het kort komt het er dus op neer dat het 2e geval de hele klasse opslaat en het 1e geval alleen enkele belangrijke gegevens (welke belangrijk zijn bepaal je in de serialize method).
Denk nu bijv. aan een Container klasse die ook shared services ondersteund (en dat is elke Container klasse). Die wil je niet cachen. Dan krijgen we een probleem met de 2e methode, omdat we dan alles opslaan, dus ook deze shared services. In het 1e geval kunnen we deze gewoon uitsluiten van het serializen.
Hmmm, oké... ik snap ongeveer wat je bedoelt, maar in de situatie zoals die bij mij is, vind ik de 2e situatie juist wel handig. Maar ik kan me nu voorstellen dat in bepaalde situaties de 1e optie inderdaad handiger is. Thanks.