relation multiple et clé composée

Bonjour,

Je viens vers vous concernant un problème que je rencontre:

J’ai:

  • une table mail qui a une clé primaire composé de 2 champs (destinataire_id et campagne_id)

  • une table lien dont l’id est lien_id

  • une table lien_mail qui associe les 2 premières (donc la clé primaire est composé de lien_id, destinataire_id et campagne_id)

Je souhaiterais avoir la liste des liens en rapport avec un mail, et c’est la où je coince.

J’ai mis un jeu d’essai dans la table lien_mail (évidement les id existent dans leur tables respectives)


lien_id / destinataire_id / campagne_id

1 / 370 / 34

2 / 370 / 34

Le traitement de test:


$test = Mail::model()->find('destinataire_id = 370 and campagne_id = 34');

print_r($test->liens);die();

Je devrais donc voir apparaître un array avec les 2 valeurs de ma table (si je fais un print_r de $test il n’y a aucun soucis je vois bien mon objet Mail)

Les différentes relations que j’ai essayé avec les messages d’erreurs qui apparaissaient:


'liens' => array(self::MANY_MANY, 'Lien', 'lien_mail(destinataire_id, campagne_id)'),


La relation « liens » définie dans l'active record « Mail » a une clef étrangère incomplète. La clef étrangère doit être constituée des colonnes qui référence les deux tables. 


------------------------------------


'liens' => array(self::MANY_MANY, 'Lien', 'lien_mail(lien_id,destinataire_id, campagne_id)'),


Array()


------------------------------------


'liens' => array(self::HAS_MANY, 'Lien', 'lien_mail(lien_id,destinataire_id, campagne_id)'),


Undefined offset: 2 

/var/www/framework/1.1.15.022/db/ar/CActiveFinder.php(665)


------------------------------------


'liens' => array(self::HAS_MANY, 'Lien', 'lien_mail(destinataire_id, campagne_id)'),


CDbCommand n'a pas pu exécuter la commande SQL : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'liens.lien_mail(destinataire_id' in 'where clause'. The SQL statement executed was:

Un idée de piste?

Salut !

Alors à mon avis la syntaxe exacte est la deuxième :




'liens' => array(self::MANY_MANY, 'Lien', 'lien_mail(lien_id,destinataire_id, campagne_id)')



Du coup je vois pas trop ce qui ne marche pas.

As-tu essayé de passer par une relation HAS_MANY associée à un "through" ?




'liensMails' => array(self::HAS_MANY, 'LienMail', 'destinataire_id, campagne_id'),

'liens' => array(self::HAS_MANY, 'Lien', array('lien_id' => 'id'), 'through' => 'liensMails'),



Ca permet de décomposer la relation et de voir si ça bloque qq part (je te conseille de faire un print_r sur $model->lienMails dans un premier temps, puis sur $model->liens).

Merci d’avoir pris le temps de me répondre.

Effectivement essayer d’afficher $model->lienMails avant d’afficher $model->liens m’a permis de cerner un peu mieux le problème. (et je ne connaissais pas l’attribut “through”)

Mais même le print_r de $model->lienMails renvoie un array vide.


 // relation du modèle Mail

'liensMails' => array(self::HAS_MANY, 'LienMail', 'destinataire_id, campagne_id'),

'liens' => array(self::HAS_MANY, 'Lien', array('lien_id' => 'id'), 'through' => 'liensMails'),

J’ai essayé l’inverse (charger un objet LienMail et afficher le mail au quelle il est associé) et cela marche, je récupère bien l’objet Mail


// relation du modèle LienMail

'mail' => array(self::BELONGS_TO, 'Mail', 'campagne_id, destinataire_id'),

Je n’ai pas pensé à le mentionner plus tôt mais j’ai utilisé Giix pour la création des modèle. (je ne pense pas que ça puisse être la cause du problème mais au cas où…) (Et non ce n’est pas tout bêtement un problème d’override des base modèle j’ai vérifié)

J’avais affiché les logs mais je n’ai rien trouvé de bien intéressant. Est-il possible d’afficher la requête SQL utilisé par Yii pour la création de ces relations? (histoire de voir le résultat sur le phpMyAdmin)

As-tu essayé de surcharger la fonction primaryKey de ton modèle qui a une clé primaire composée ?




// Mail

public function primaryKey()

{

    return array('destinataire_id', 'campagne_id');

}



Oui j’avais essayé (mais pas avec les dernières modifications). J’étais tombé sur ce topic lors de mes recherches : http://stackoverflow.com/questions/24670359/yii-many-to-many-relationship-and-composite-primary-key

(j’avais abandonné cette piste car je ne comprenais pas trop d’où venait ce ‘t’ de ‘t.someOtherID’ dans la condition, et en plus personne n’avait répondu pour savoir si cela fonctionnait réellement)

Je viens de remettre la fonction mais aucun changement, toujours un array vide.

J’ai aussi essayé d’hérité de ActiveRecord au lieu de GxActiveRecord pour être sur que ça ne soit pas la surcouche giix qui pose problème (j’ai fait la modification sur les 3 modèles) mais toujours pareil.

J’ai bien regardé que je n’ai pas fait de faute dans les différentes valeurs mais ce n’est pas le cas.

Et de toute manière dès qu’il y a une erreur on se fait insulter par l’application, alors que la ça donne l’impression que cela marche mais qu’il n’y a pas de résultat dans ce sens (Mail -> LienMail)

Pourtant on peut bien faire le chemin inverse (LienMail -> Mail)

Pour tester mon modèle Mail j’ai ajouté une relation:


'destinataire' => array(self::BELONGS_TO, 'Destinataire', 'destinataire_id'),

Je n’ai aucun soucis à accéder à ces objets…

D’après la description de tes tables dans ton premier message tu devrais plutôt écrire ça :


'liensMails' => array(self::HAS_MANY, 'LienMail', 'destinataire_id, campagne_id'),

'liens' => array(self::HAS_MANY, 'Lien', array('lien_id' => 'lien_id'), 'through' => 'liensMails'),

indique lien_id dans ton array au lieu de id

En fait j’avais bien corrigé ‘lien_id’ dans mon développement mais quand j’ai écrit mon post j’ai juste récupéré le texte du post précédent.

Mais même avec l’erreur je bloque avant, je ne peux pas faire le lien avec la table associative lien_mail

Dans Mail, essaie ça :


'liensMails' => array(self::HAS_MANY, 'LienMail', array('destinataire_id'=>'destinataire_id','campagne_id'=>'campagne_id')),

'liens' => array(self::HAS_MANY, 'Lien', array('lien_id' => 'lien_id'), 'through' => 'liensMails'),

Magnifique c’était bien ça !! (et du coup pas de soucis non plus pour accéder au $model->liens)

Une idée du besoin de cette syntaxe? J’aurais du nommer différemment mes clefs primaire/étrangère pour éviter toute confusion?

En tout cas merci beaucoup pour votre aide à tous les deux, ça faisait quelques jours que je butais sur ce problème…

Cette syntaxe permet de spécifier précisément la relation entre la clé primaire et la clé étrangère et permet justement d’avoir un nom de clé différent en plis de gérer la clé multiple.