Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
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 23/11/2010, 16h47   #1
Membre habitué
 
Avatar de Vicrabb
 
Femme Vinciane
Développeur Web
Inscription : novembre 2010
Messages : 66
Détails du profil
Informations personnelles :
Nom : Femme Vinciane
Âge : 29
Localisation : Belgique

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : novembre 2010
Messages : 66
Points : 100
Points : 100
Par défaut Problème de sauvegarde des données avec embed form

Hello,

J'essaie de maîtriser un minimum symfony mais je suis bloquée au niveau des embed forms et de l'enregistrement des données quand il s'agit de relations n:n.
J'ai une table Jeux, une table Genre et une table JeuxHasGenre (avec comme colonnes: jeux_id_jeux et genre_id_genre) qui permet d'associer un jeu avec ses genres (ou un genre avec les jeux associés).


[Première problème résolu]
Mon premier problème est que si j'envoie plusieurs genres à la fois pour un jeu, il y a une requête SQL de Doctrine qui m'empêche d'aller plus loin (Select Count* etc. en mettant une clause WHERE id_genre = ? (valeurs envoyées - ids genre).

Désireuse d'avancer, je n'envoie qu'un seul genre et bardaf, c'est l'embardée. Enfin, si on préfère, mon formulaire a un formulaire imbriqué concernant les genres. C'est une manière de récupérer l'id du nouveau insert mais voilà, dès qu'on arrive à l'insert dans la table JeuxHasGenre, j'ai donc cet id mais PAS l'id du genre sélectionné dans le formulaire. Pourtant, la fameuse requête SQL de mon premier problème récupère la donnée.

J'ai donc l'erreur suivante - je vous mets les logs avec les requêtes:
Code :
1
2
3
4
5
 
6	Info Doctrine_Connection_Statement	execute : SELECT COUNT(*) AS num_results FROM genre g WHERE g.id_genre = ? - (14)
7	Info Doctrine_Connection_Statement	execute : INSERT INTO jeux (developer, publisher, nom_jeu, background, release_date) VALUES (?, ?, ?, ?, ?) - (lb k, llbk, cjvj, bljhn,cghc, 2006-04-03)
8	Info Doctrine_Connection_Statement	execute : INSERT INTO jeux_has_genre (jeux_id_jeu) VALUES (?) - (29)
9	Error Doctrine_Connection_Mysql_Exception	SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`test_project`.`jeux_has_genre`, CONSTRAINT `jeux_has_genre_genre_id_genre_genre_id_genre` FOREIGN KEY (`genre_id_genre`) REFERENCES `genre` (`id_genre`))
Voici le schéma de ma base de donnée réalisée avec un modèle de mysql workbench:

Code :
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Genre:
  connection: doctrine
  tableName: genre
  columns:
    id_genre:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: true
    nom_genre:
      type: string(50)
      fixed: true
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    JeuxHasGenre:
      local: id_genre
      foreign: genre_id_genre
      type: many
Jeux:
  connection: doctrine
  tableName: jeux
  columns:
    id_jeu:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: true
    nom_jeu:
      type: string(255)
      fixed: true
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    developer:
      type: string(100)
      fixed: true
      unsigned: false
      primary: false
      default: Inconnu
      notnull: false
      autoincrement: false
    publisher:
      type: string(100)
      fixed: true
      unsigned: false
      primary: false
      default: Inconnu
      notnull: false
      autoincrement: false
    background:
      type: string()
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
    release_date:
      type: date(25)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
    is_on_steam:
      type: integer(1)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
  relations:
    JeuxHasGenre:
      local: id_jeu
      foreign: jeux_id_jeu
      type: many
    PlatformsHasJeux:
      local: id_jeu
      foreign: jeux_id_jeu
      type: many
JeuxHasGenre:
  connection: doctrine
  tableName: jeux_has_genre
  columns:
    jeux_id_jeu:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    genre_id_genre:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
  relations:
    Genre:
      local: genre_id_genre
      foreign: id_genre
      type: one
    Jeux:
      local: jeux_id_jeu
      foreign: id_jeu
      type: one
Voici ce qu'il y a dans JeuxForm (formulaire principal):

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class JeuxForm extends BaseJeuxForm
{
  public function configure()
  {
    unset ($this['is_on_steam']);
 
    $game = new JeuxHasGenre();
 
    $game->Jeux = $this->getObject();
 
    $this->embedForm('genres',new JeuxHasGenreForm($game));
 
    $this->widgetSchema->setLabels(array(
      'nom_jeu'    => 'Game',
      'is_on_steam'=> 'Is on Steam?'
      ));
 
  }
Voici le code dans JeuxHasGenreForm:

Code :
1
2
3
4
5
6
7
8
9
class JeuxHasGenreForm extends BaseJeuxHasGenreForm
{
  public function configure()
  {
      unset ($this['genre_id_genre']);
    $this->widgetSchema['genre'] = new sfWidgetFormDoctrineChoice (array('model'=> 'genre', 'choices'=> Doctrine_Core::getTable('genre'), 'multiple'=>true, 'expanded'=>true));
    $this->validatorSchema['genre'] = new sfValidatorDoctrineChoice (array('model'=>'genre'));
  }
}
J'ai essayé plusieurs solutions style saveembeddedform() mais je n'arrive pas à bidouiller mon code convenablement. Si quelqu'un pouvait m'aider, même m'aiguiller, j'en serai reconnaissante.

Merci d'avance

Vic

EDIT: Etant donné que mon premier problème est résolu, je donne ici la solution. Mais le deuxième est toujours en train de me donner des maux de tête.
Code :
1
2
3
4
5
6
7
8
9
10
11
class JeuxHasGenreForm extends BaseJeuxHasGenreForm
{
  public function configure()
  {
    unset ($this['genre_id_genre']);
 
 
    $this->widgetSchema['genre'] = new sfWidgetFormDoctrineChoice (array('model'=> 'genre', 'choices'=> Doctrine_Core::getTable('genre'), 'multiple'=>true, 'expanded'=>true));
    $this->validatorSchema['genre'] = new sfValidatorDoctrineChoice (array('model'=>'genre', 'multiple' => true));//en fait, le validateur doit avoir aussi l'attribut multiple à true.
  }
}
Vicrabb est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/11/2010, 11h31   #2
Membre chevronné
 
Avatar de Herode
 
Développeur Web
Inscription : mars 2005
Messages : 767
Détails du profil
Informations personnelles :
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : mars 2005
Messages : 767
Points : 785
Points : 785
Je ne sais pas quel est le deuxième problème mais une cause fréquente de bugs est un schema.yml mal déclaré. Comme le signalait Michel Rotta dans un autre fil, il vaut mieux construire le fichier schema.yml proprement et créer la base à partir de là (avec la tâche doctrine:build) plutôt que de créer la base de données et en extraire le fichier .yml avec un build-schema.

Dans ton cas, tu as une relation n-n et Doctrine prévoit une manière bien plus simple de déclarer cela que ce que je vois dans ton fichier :
Relations n-n dans le fichier schema.yml

Il y a un cas d'application dans le tutoriel Jobeet, à consulter impérativement.

En simplifiant ton schema (je conserve une colonne par table pour alléger la présentation), cela donnerait quelque chose du style :
Code :
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
Genre:
  columns:
    nom_genre:
      type: string(50)
      notnull: true
  relations:
    Jeux:
      refClass: JeuxHasGenre
      foreignAlias: Genres
 
Jeux:
  columns:
    nom_jeu:
      type: string(255)
      notnull: true
 
JeuxHasGenre:
  columns:
    jeux_id:
      type: integer
      primary: true
    genre_id:
      type: integer
      primary: true
  relations:
    Genre:
      onDelete: cascade
      onUpdate: cascade
    Jeux:
      onDelete: cascade
      onUpdate: cascade
NB : Pour simplifier, les conventions Doctrine ont été conservées :
- colonne id déclaré implicitement si aucune autre primary_key n'est déclarée
- clé étrangère sur une table MaTable : ma_table_id

Avec ça et éventuellement l'utilisation d'embedRelations() dans ton formulaire, ça devrait aller mieux. Voir cet autre tuto pour les détails :
http://www.symfony-project.org/more-...ymfony/1_4/en/
Herode est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 24/11/2010, 12h11   #3
Membre habitué
 
Avatar de Vicrabb
 
Femme Vinciane
Développeur Web
Inscription : novembre 2010
Messages : 66
Détails du profil
Informations personnelles :
Nom : Femme Vinciane
Âge : 29
Localisation : Belgique

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : novembre 2010
Messages : 66
Points : 100
Points : 100
En fait, j'ai déjà fait Jobeet mais j'ai plus appris avec mon projet test qu'en suivant le tuto. Et j'ai déjà consulté la doc sur les formulaires avancés mais bon, peut-être qu'en changeant le schema, ça marchera.

Je vais changer cela maintenant et tester l'embed relation... après la pause midi

EDIT: Merci pour le renseignement sur les relations doctrine, non seulement, ca m'a permis de mieux comprendre cette partie-là mais en plus, c'était bien un problème de ce côté-là.

Voici pour ceux que cela intéresse mon schema (en fait, j'ai recommencé un nouveau projet mais les tables ont les mêmes relations) - les ids étant mis pour respecter ce que j'ai vu sur Doctrine et sur Jobeet après réexamen du schema.yml.

Code :
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 
Game:
  columns:
    id:
      type: integer(4)
      autoincrement: true
      primary: true
    name_game:
      type: string(255)
      notnull: true
    developer:
      type: string(100)
      default: Inconnu
    publisher:
      type: string(100)
      default: Inconnu
    background:
      type: string()
    release_date:
      type: date(25)
 
Genre:
  columns:
    id:
      type: integer(4)
      autoincrement: true
      primary: true
    name_genre:
      type: string(50)
      notnull: true
  relations:
    Games:
      foreignAlias: Genres
      class: Game
      refClass: GameGenre
      local: genre_id
      foreign: game_id
 
GameGenre:
  columns:
    game_id:
      type: integer(4)
      primary: true
    genre_id:
      type: integer(4)
      primary: true
  relations:
    Genre:
      onDelete: cascade
      local: genre_id
      foreign: id
      foreignAlias: GameGenres
    Game:
      onDelete: cascade
      local: game_id
      foreign: id
      foreignAlias: GameGenres
Vicrabb est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h15.


 
 
 
 
Partenaires

Hébergement Web