Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 03-12-2007 15:55:07

MaitrePylos
Membre
Date d'inscription: 04-09-2007
Messages: 11

Persistance des données

Bonjour, existe-il sur Zend un système de persistance de données, un peu comme un dataSet, que je pourrais garder de fonction en fonction.

En gros malgré l'afichage plus besoin de fiare une requête pour afficher les mêmes données dans une autre vue.

Merci de votre aide.

Hors ligne

 

#2 03-12-2007 16:13:58

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

oui il faut convertir tous tes objet en StdClass objects et les mettre en sessions
ainsi il sont dispos durant toute la session de l'utilisateur

si tu mets des objets qui ne sont pas des StdClass en session il te faut être sur que la classe correspondante est chargée avant l'ouverture de la session
ce qui revient à dire que toute classe dont tu mets à un moment ou un autre un objet en session doit être chargée avant le démarrage du framework dans toutes les pages.

J'ai envisagé de faire un parsing du fichier de session avant le démarrage du framework pour vérifier la présence de classes et les charger au besoin mais je n'ai pas trouver de moyen performant de le faire.

je place donc des StdClass object dans la session et je le transforme en les sortant de la session.

A+JYT

Hors ligne

 

#3 03-12-2007 19:58:20

2mx
Membre
Lieu: Grenoble
Date d'inscription: 06-08-2007
Messages: 125

Re: Persistance des données

sekaijin a écrit:

oui il faut convertir tous tes objet en StdClass objects et les mettre en sessions
ainsi il sont dispos durant toute la session de l'utilisateur

si tu mets des objets qui ne sont pas des StdClass en session il te faut être sur que la classe correspondante est chargée avant l'ouverture de la session

Sauf si tu sérialise tes objets, dans se cas lors de session_start() se ne sont que des chaines de caractères.

Tu peux ensuite loader la class et déséralisé ton objet.

Plus d'explication ici :
http://www.z-f.fr/forum/viewtopic.php?pid=3285#p3285

Hors ligne

 

#4 03-12-2007 20:20:47

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

il faut noter que les objet en session sont déjà sérialisé
mais c'est effectivement une solution
pour ma part j'ai ajouté une méthode getStdClassObject() à mes objets et en général mes constructeurs savent reconstruire l'objet depuis un StdClass

A+JYT

Hors ligne

 

#5 03-12-2007 22:23:08

Julien
Membre
Date d'inscription: 16-03-2007
Messages: 501

Re: Persistance des données

Je vais faire un petit point : toute donnée composite ( array, objet ) est systématiquement sérialisée avant d'entrer en session. la simple affectation $_SESSION['test'] = $object , appelle serialize() automatiquement dessus.
Ceci est personnalisable via php.ini.

Si la classe de l'objet contient les méthodes magiques __sleep() et __wakeup(), alors elles sont implicitement appelées  respectivement à la sérialisation, et à la désérialisation.

Zend_Db_Table_Row est prévu pour cela. A l'entrée en session, les objets sont deconnectés de la base de donnée ( grace à __sleep() ), car une connexion a une base de données est de type ressource, ce qui ne peut être sérialisé (normal).
Une fois l'objet sorti de la session, __wakeup() le marque comme non connecté. Il faudra alors spécifiquement le reconnecter à sa table ( et donc, à la base de données ) si on veut pouvoir faire intervenir la base (le sauvegarder, par exemple).

Bien entendu la classe d'un objet doit avoir été déclarée avant sa désérialisation, soit : avant un session_start(), dans le cas contraire, PHP ne sait redéfinir l'objet, et l'affecte donc à la __PHP_Incomplete_Class , l'objet garde toutes ses propriétés intactes, mais perd ses méthodes, et sa classe d'origine.
http://www.z-f.fr/forum/viewtopic.php?pid=3285#p3285 ce lien là illustre parfaitement le comportement expliqué ici.

Hors ligne

 

#6 04-12-2007 07:25:15

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

pour ceux qui voudraient connaître la liste des classes dont des objets sont dans la session avant l'ouverture de celle-ci un objet sérialisé est transformé en chaîne de caractères du genre (de mémoire) {o:class:s:8:"client":{.....}} qui dit en gros o pour object puis le nom de la classe et entre {} le contenu de l'objet
on peu donc repérer dans la chaîne toute les portion {o:class:s:  ([0-9]+):"([^:]+):{ pour trouver le nom de toute les classes.

cela sera suffisent pour ne pas avoir de pb à la désérialisation (en chargeant ces classes avant le session_start) mais comme le dit julien ça ne reconstruit pas les liens vec les ressources.

A+JYT

Dernière modification par sekaijin (04-12-2007 07:25:47)

Hors ligne

 

#7 04-12-2007 09:40:44

2mx
Membre
Lieu: Grenoble
Date d'inscription: 06-08-2007
Messages: 125

Re: Persistance des données

Julien a écrit:

Bien entendu la classe d'un objet doit avoir été déclarée avant sa désérialisation, soit : avant un session_start(), dans le cas contraire, PHP ne sait redéfinir l'objet, et l'affecte donc à la __PHP_Incomplete_Class , l'objet garde toutes ses propriétés intactes, mais perd ses méthodes, et sa classe d'origine.

Je ne suis pas très pointu sur ce sujet, mais il me semble que si l'on charge la classe après un session start ça marche très bien. J'ai fait un petit test pour vérifier :

Code:

session_start();
require_once 'Zend/Db/Table/Row.php';
$articleRow = unserialize($_SESSION['article']);
echo get_class($articleRow);

Ceci m'affiche Zend_Db_Table_Row


Par contre si j'omets "require_once 'Zend/Db/Table/Row.php';", jai bien un
__PHP_Incomplete_Class

Dernière modification par 2mx (04-12-2007 09:44:43)

Hors ligne

 

#8 04-12-2007 10:00:53

Julien
Membre
Date d'inscription: 16-03-2007
Messages: 501

Re: Persistance des données

Normal : tu sérialises à la main.
Je parles lorsque tu laisses PHP sérialiser lui même tes données. Je répète qu'il n'est pas nécéssaire de sérialiser à la main, avant le passage en session.

Pour ceux qui aiment se croquer le cerveau, il existe une interface serializable ( qui est intéressante pour les objets qui gèrent eux même leur propre sérialisation, et celle de leurs enfants ).

Hors ligne

 

#9 04-12-2007 10:26:01

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

c'est parce que tu as sérialisé tes objet avant de les mettre en session et que le système a sérialisé la sérialisation pour sauver la session

Code:

$_SESSION['toto'] = new MyClass($data);

lorsque le script se termine $_SESSION est sérialisé et enregistré sur le disque
lorsque tu ouvre ensuite un autre script

Code:

session_start();
Zend_Db::loadClass('MyClass');
echo get_class($_SESSION['toto']);

te donne : __PHP_Incomplete_Class
par contre si tu fais

Code:

Zend_Db::loadClass('MyClass');
session_start();
echo get_class($_SESSION['toto']);

tu obtiens : MyClass

pour revenir sur mon précédent post ce qui est enregistré sur le disque dans c'est exemple est

Code:

a:1:{s:4:"toto";O:7:"MyClass":1:{s:1:"a";i:45;}}

a: la session est un tableau
1: qui contient 1 élément
{s:4"toto"; dont la clef est la chaine (s: ) de longueur 4 (4: ) et de valeur toto
O: et le contenu un objet
7: don la classe à un nom sur 7 caractère
"MyClass": de nom MyClass
1: qui a un membre
{s:1:"a"; dont le nom est une chaine de 1 caractère de valeur a
i:45; et dont la valeur est un entier (i: ) de valeur 45

pour retrouver le nom de la classe il faut repérer ;O:7:"MyClass": pour pouvoir la charger avant
sinon il faut être sur que tu charge bien toutes les classe possible.

Code:

preg_match_all('|;O:[0-9]+:"([^"]+)":|', $serializedData, $matches);

$matches[1] contient alors le tableau de toute les classes présentes dans la session (attention au doublon)

ta solution consiste à sérialiser une première fois l'objet (qui est donc inexploitable dans la session) pour placer la chaîne dans la session et la retirer pour reconstruire l'objet
ainsi :

Code:

a:1:{s:4:"toto";s:31:"O:7:"myclass":1:{s:1:"a";i:45;}";}

ce coup ci dans la saision nous avons toujours 1 élément a:1:{s:4:"toto"; qui ce coup ci est une chaine
s:31:"..........";}
il est donc impossible ni dans le premier script ni dans le second de faire

Code:

$_SESSION['toto'] = new MyClass($data);
$_SESSION['toto']->getMyName();

ou dans le second

Code:

$_SESSION['toto']->getMyName();

mais effectivement ça supprime les __PHP_Incomplete_Class puisque tu ne mets jamais d'objet dans la session.

A+JYT

Dernière modification par sekaijin (04-12-2007 10:30:34)

Hors ligne

 

#10 04-12-2007 10:41:51

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

Julien a écrit:

Normal : tu sérialises à la main.
Je parles lorsque tu laisses PHP sérialiser lui même tes données. Je répète qu'il n'est pas nécéssaire de sérialiser à la main, avant le passage en session.

Pour ceux qui aiment se croquer le cerveau, il existe une interface serializable ( qui est intéressante pour les objets qui gèrent eux même leur propre sérialisation, et celle de leurs enfants ).

oui j'ai utilisé cette solution. dans la sérialisation je débarrassais (une copie de) l'objet des élément non sérialisable (resources) et et je lui changeais sa classe en StdClass

du coup lorsque tu mets un truc en session tu peux continuer à l'utiliser dans ton script
mais une fois le script fermé ne sont gardé en session que les données de cet objet.

à l'ouverture du nouveau script au moment ou tu en a besoin tu peux récupérer les données et reconstruire une nouvel objet avec les nouvelles ressources disponible.
Mais ce ne peu ce faire à la désérialisation car sinon on retombe sur le même problème.

A+JYT

Dernière modification par sekaijin (04-12-2007 10:43:53)

Hors ligne

 

#11 04-12-2007 11:07:40

2mx
Membre
Lieu: Grenoble
Date d'inscription: 06-08-2007
Messages: 125

Re: Persistance des données

Julien a écrit:

Normal : tu sérialises à la main. ... Je répète qu'il n'est pas nécéssaire de sérialiser à la main, avant le passage en session...

Oui, je suis d'accord, ce que je voulais dire, c'est que l'on est pas obligé de charger les classes avant session_start(), surtout si l'on  utilise MVC et que le session_start() est dans le bootstrap.

Donc si l'on veut éviter de charger les classes avant session_start(), et si j'ai bien tout compris, on a 2 solutions :

* On sérialise à la main avec dans l'idéale une class qui implémente l'interface serializable
* On utilise la technique de sekaijin avec la StdClass et des classes qui implémente toStdClass() et setFromStdClass() ce qui nous évite de sérialisé à la main.

Dernière modification par 2mx (04-12-2007 11:35:40)

Hors ligne

 

#12 13-12-2007 08:17:01

MaitrePylos
Membre
Date d'inscription: 04-09-2007
Messages: 11

Re: Persistance des données

Merci pour cet éclairage.

MaitrePylos

Hors ligne

 

#13 19-12-2007 13:58:45

Moimeme
Membre
Date d'inscription: 19-04-2007
Messages: 120

Re: Persistance des données

Est il pertinent de mettre beaucoup de chose en session ? sur quoi cela influe les perfs si j'abuse des sessions genre que je mets des dizaines de gros objets dedans, multiplié par des dizaines d'utilisateurs connectés quel risque je prends à faire cela ?

Hors ligne

 

#14 19-12-2007 14:33:38

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Persistance des données

la session est gardée dans un fichier (sauf si tu mets en place ton propre gestionnaire de session)
ce fichier reste en mémoire cache un certain temps. donc si tu sollicite ton serveur souvent il n'y a pas d'impact sur les perfs. juste le temps de sérialiser désérialiser.
si tu mets de gros volumes de données et que tu as beaucoup d'utilisateurs, le serveur vas délester la mémoire des sessions les plus anciennes du coup pour y accéder de nouveau tu vas devoir accéder au disque ce qui est consommateur de temps. de plus s'il y a beaucoup d'utilisateur et de très gros volumes de données tu mange de la mémoire. tu risque donc de ne plus avoir assez de place pour faire tes traitements.

imagine un script simple sans beaucoup de variables qui mets des choses en session jusqu'à presque atteindre la taille maximale autorisée. tu fini ton script et tu en ouvre un autre qui charge la session et fais beaucoup de traitement allouant beaucoup de variables. tu peux arriver à un moment ou tu n'a plus d'espace dispo pour ta variable et le script plante. (Il faut être très gourmand mais ça arrive)

la mise en session doit toujours répondre à un équilibre entre garder une donnée est consommer de l'espace ou aller la chercher à chaque fois et donc consommer du temps et des ressources.

A+JYT

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages