Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > ORM > Doctrine
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 15/02/2011, 11h48   #1
Invité de passage
 
Inscription : septembre 2008
Messages : 19
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 19
Points : 1
Points : 1
Par défaut Sérialisation Doctrine_record et identifiant

Bonjour,

Je travaille à un projet avec Zend Framework et Doctrine 1.x.

Je rencontre un problème dans la sérialisation de mes objets Doctrine_Record.
Pour faire simple, j'ai comme objet central un ouvrage (Publications_Model_Book) auquel je rattache différents objets de classement et notamment un éditeur et des collections.

Mon formulaire de création est multi-étapes ce qui signifie que je dois placer en session les différents objets Doctrine_Record créés lors de ces étapes. Pour placer ces objets en session je les transforme en tableau avec la méthode toArray(true) et je les recréé avec la méthode fromArray.

Il se trouve que cela fonctionne parfaitement pour la plupart des champs sauf les identifiants qui semblent perdus entre chaque session.

Avez-vous une idée comment gérer les identifiants lors de la sérialisation ?


Merci beaucoup par avance,

Frédéric
fhebert est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 12h33   #2
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Je n'ai jamais fais, ni eu le besoin de faire.

Par contre, doctrine embarque le paterne de sérialize. Je pense que tu aurais plutôt intérêt a sérialiser plutôt que d'envoyer vers un array().
Code :
1
2
3
 
$string = serialize($record);
$record = unserialize($string);
Par contre je ne vois pas bien comment tu veux gérer tes identifiants. A priori ton problème vient que tu veux "sauvegarder" temporairement un enregistrement maître (qui n'existe que virtuellement) et les enregistrements enfants qui lui sont liés sur l'identifiant (Id en général). Sauf que si tu utilises les fonctions de base de Doctrine, l'Id en question n'est pas créé par Doctrine mais par la base de donnée. Il n'est envoyé à doctrine qu'après la première sauvegarde. Hors tu ne veux pas sauvegarder...

Je pense que tu as intérêt à procéder en plusieurs étapes distincte création du record de base, des records lié mais sans le lien. Sauvegarde du principal. Attachement du principal à ces enfants et sauvegarde des enfants.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 13h32   #3
Invité de passage
 
Inscription : septembre 2008
Messages : 19
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 19
Points : 1
Points : 1
Par défaut Re:

Bonjour,

tu as bien compris ce que je veux faire. Le problème est que ce formulaire est utilisé à la fois pour la création d'un nouvel ouvrage et pour l'édition d'un ouvrage existant.

En fait les identifiants sont parfois déjà créés (les objets existent déjà en base de données), comme par exemple quand je veux lier un éditeur déjà créé à un ouvrage.

Le principe des identifiants fonctionne bien dans mon appli il me semble, les problèmes arrivant après "sérialisation".

Je pense que tu as raison sur la méthode de sérialisation. Avec toArray/fromArray Doctrine considère que l'on veut transférer des données d'un objet à un autre ; c'est lorsque l'on sérialise réellement que l'objet complet peut-être recréé.

J'ai utilisé toArray/fromArray après la lecture d'un article de blog évoquant le fait que la sérialisation d'un objet Doctrine_Record pouvait être une sérieuse pénalité pour les sessions (en terme de performance et de mémoire consommée), dans la mesure où la sérialisation conserve les différentes informations sur les états des objets.

Merci de ton aide en tout cas !

Frédéric
fhebert est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 14h31   #4
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Si tu travailles en MCV tu peux avoir un même formulaire mais des traitements différent suivant que tu es en création ou en édition. Personnellement je travail avec symfony et c'est quelque chose que j'ai déjà implémenté régulièrement.

Je pense (mais il faudrait analyser plus près le code (le tiens et celui de Doctrine) ) que c'est lors de la unserial() que l'absence de Id réel apparait.

Il reste la possibilité de ne pas déléguer à la base de donnée le soins de créer l'Id de l'objet et de le faire directement. De l'attribuer dés la première création bien avant la première sauvegarde, quitte à perdre quelques numéro.

Regarde aussi du côté de Doctrine 2 qui est sorti il y a peu. Il est possible qu'il gère mieux ce type de problème et, accessoirement, les performances sont largement dopées et le système beaucoup plus souple. Ça vaut la peine de s'y pencher. Seul bémol, la documentation périphérique qui manque encore largement.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h04   #5
Invité de passage
 
Inscription : septembre 2008
Messages : 19
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 19
Points : 1
Points : 1
Par défaut Re:

Je commence à utiliser les fonctions serialize/unserialize sur mes modèles.

Il y a un truc énervant c'est que les références ne sont pas sérialisées récursivement.

J'ai bien trouvé la méthode serializeReferences(bool) et je l'utilise sur mon modèle Book pour les objets liés.

Mais par contre cette sérialisation ne se fait pas en profondeur. D'après le code de la méthode Doctrine_record::serialize il faut paramêtrer cela pour chaque objet lié.

Par exemple : dans mon modèle objet, un livre est lié à un Identifier qui est lui-même lié à un IdentifierType (ISBN13, ISBN10, EAN13) ; ex. :

Code :
Book->Identifier->identifierType
Du coup mon Identifiertype n'apparaît pas à la désérailisation.

J'ai trouvé comme moyen temporaire de modifier le constructeur de mes modèles pour inclure l'appel à la méthode serializeReferences.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
 
//Exemple pour l'identifier :
 
class Publications_Model_Identifier extends Publications_Model_Base_Identifier
{
 
	public function __construct($table = null, $isNewEntry = true)
	{
		parent::__construct($table, $isNewEntry);
		$this->serializeReferences(true);
	}
}
Qu'en penses-tu ?


Merci encore
fhebert est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h17   #6
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Je pense que tu serais beaucoup plus à l'aise avec Doctrine 2.

En effet, il conserve nativement les enregistrements entre les sessions avant de les enregistrer.

Donc tu fais tes modifications, tu récupères ton enregistrement d'une session à une autre, et tu enregistres quant tu as terminé. Du moins en théorie, en pratique, je n'ai pas encore testé.


Je pense que, sur Doctrine 1, la sérialisation est orienté mono enregistrement (ou valable pour une collection et encore) et que vouloir modifier comme tu le fais me semble un sac à bug à moyenne échéance. Une des raisons de la création de Doctrine 2 était l'impossibilité de conserver des lots d'enregistrements entre deux appels d'une même session. Et les équipes de Doctrine on considéré que ce n'était pas faisable dans la version 1. M'est avis que tu vas plus loin que ce que sait faire le produit.

La seul fois où j'ai eu à faire ce type de manipulation, ma solution a été de créer en base avec un flag sur le principale et de purger régulièrement la base des créations non terminées. Brutal mais efficace.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 19h06   #7
Invité de passage
 
Inscription : septembre 2008
Messages : 19
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 19
Points : 1
Points : 1
Par défaut Re:

à vrai dire c'est la première fois que j'utilise Doctrine.

Et je crois que tu as tout-à-fait raison pour le côté sac à bug de ce genre d'utilisation de Doctrine 1.x
Il vient d'ailleurs de s'ouvrir quand j'ai voulu sauvegarder l'objet central en base à la fin du processus de saisie. J'obtiens l'erreur MySQL suivante :

Code :
1
2
 
SQLSTATE[23000]: Integrity constraint violation: 1048
sur la clef locale book_id du premier objet référencé sauvegarder.

Je vais donc effectivement sauver mes objets au fur et à mesure (en commençant par l'objet principal) en attendant de mieux comprendre Doctrine et d'utiliser Doctrine 2.0

Je suis quand même super étonné ayant été habitué à l'ORM de Django qui gère ça sans trop de pb (je veux dire sauvegarder les composants liés d'un nouvel enregistrement principal).

En tout cas grand merci à toi !

Frédéric
fhebert est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 10h54   #8
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Bonne chance pour la suite.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 10h54.


 
 
 
 
Partenaires

Hébergement Web