Bonjour à tous,
je suis toujours sur mes problèmes de relations n-n réflexives. Il s'agit ici de produits croisés : un produit peut pointer 0-n autres produits (qui seront proposés comme produits similaires au visiteur du site).
Avec ce schéma, Symfony me génère des modèles et des formulaires qui me vont bien, je peux faire mes associations. Mais j'ai besoin de rendre la relation symétrique : si un produit P1 est lié à un produit P2, alors P2 doit être aussi lié à P1. Pour y arriver, mon idée était de surcharger le doSave() du formulaire pour y ajouter les ProductLinks ad hoc et sauvegarder tout ça. La tentative plante lamentablement, je désactive mon code, je mets des traces dans le doSave() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 Product: columns: name: type: string(45) notnull: true relations: Links: refClass: ProductLink class: Product local: product_id foreign: linked_product_id ProductLink: columns: product_id: type: integer primary: true notnull: true linked_product_id: type: integer primary: true notnull: true relations: LinkingProduct: class: Product local: product_id foreignAlias: AsLinker onDelete : cascade onUpdate : cascade LinkedProduct: class: Product local: linked_product_id foreignAlias: AsLinked onDelete : cascade onUpdate : cascade
et voici le résultat : le produit qui fait les liens est celui d'id #3, les 3 produits liés sont d'id 1, 2, 4 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 protected function doSave($conn = null) { sfContext::getInstance()->getLogger()->debug(__METHOD__ . " avant parent::doSave ligne " . __LINE__); parent::doSave($conn); sfContext::getInstance()->getLogger()->debug(__METHOD__ . " après parent::doSave ligne " . __LINE__); $product = $this->getObject(); // La relation 'produits croisés' est commutative : on s'assure donc que les entrées symétriques // à celles du formulaire existent : si #6 est lié à #7, #7 sera lié à #6. $linkedProducts = $product->getLinks(); foreach ($linkedProducts as $linked) { $lp = $product->createLinker($linked); sfContext::getInstance()->getLogger()->debug(__METHOD__ . " avant save ligne " . __LINE__); $lp->save(); sfContext::getInstance()->getLogger()->debug(__METHOD__ . " après save ligne " . __LINE__); } }
Dec 02 11:02:20 symfony [debug] ProductForm::doSave avant parent::doSave ligne 84
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : DELETE FROM product_link WHERE (linked_product_id = ? AND product_id IN (?, ?, ?)) - (3, 1, 2, 4)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : UPDATE product_link SET linked_product_id = ? WHERE product_id = ? AND linked_product_id = ? - (1, 1, 3)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : UPDATE product_link SET linked_product_id = ? WHERE product_id = ? AND linked_product_id = ? - (2, 2, 3)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : UPDATE product_link SET linked_product_id = ? WHERE product_id = ? AND linked_product_id = ? - (4, 4, 3)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : DELETE FROM product_link WHERE product_id = ? AND linked_product_id = ? - (1, 3)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : DELETE FROM product_link WHERE product_id = ? AND linked_product_id = ? - (2, 3)
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : DELETE FROM product_link WHERE product_id = ? AND linked_product_id = ? - (4, 3)
Dec 02 11:02:20 symfony [debug] ProductForm::doSave après parent::doSave ligne 86
Dec 02 11:02:20 symfony [debug] ProductForm::doSave avant save ligne 94
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO product_link (linked_product_id, product_id, created_at) VALUES (?, ?, ?) - (3, 1, 2010-12-02 11:02:20)
Dec 02 11:02:20 symfony [debug] ProductForm::doSave après save ligne 96
Dec 02 11:02:20 symfony [debug] ProductForm::doSave avant save ligne 94
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO product_link (linked_product_id, product_id, created_at) VALUES (?, ?, ?) - (3, 2, 2010-12-02 11:02:20)
Dec 02 11:02:20 symfony [debug] ProductForm::doSave après save ligne 96
Dec 02 11:02:20 symfony [debug] ProductForm::doSave avant save ligne 94
Dec 02 11:02:20 symfony [info] {Doctrine_Connection_Statement} execute : INSERT INTO product_link (linked_product_id, product_id, created_at) VALUES (?, ?, ?) - (3, 4, 2010-12-02 11:02:20)
Dec 02 11:02:20 symfony [debug] ProductForm::doSave après save ligne 96
Le premier DELETE me laisse déjà perplexe car Symfony me supprime d'office tous les liens pointant vers mon produit, ce qui n'est pas demandé ici.
Les trois UPDATE qui suivent, je ne les comprends tout simplement pas : ils vont créer dans la table ProductLink des entrées avec des produits se pointant eux-mêmes, ce qui est évidemment faux.
Et ces entrées calamiteuses sont de toutes façons supprimées par les 3 DELETE qui suivent...
Toutes ces requêtes abracadabrantes disparaissent si je retire ma surcharge, bien sûr. Mais je ne comprends pas
- pourquoi Symfony génère ces requêtes aussi aberrantes ?
- comment faire pour automatiser la création de liens symétriques ?
Partager