2010-03-05 6 views
-1

J'utilise Cake 1.2.6 et la nuit dernière, j'ai remarqué qu'une relation HABTM n'était pas enregistrée lorsque je soumettais un formulaire. J'ai une relation HABTM entre Committee et Volunteer. La clé primaire pour un Volunteer est un UUID tandis que la clé primaire pour un Committee est une chaîne lisible par un humain (par exemple BOARDOFDIRECTORS, FAIRCOMMITTEE, FAIRASSOCIATES, etc.). J'ai un formulaire pour créer/éditer des volontaires et ce formulaire inclut une boîte de sélection dont les options sont exactement ce que vous attendez et sont peuplées avec des options retournées par la méthode de Cake. Bien que je ne puisse pas penser à une raison pour laquelle cela aurait de l'importance, un seul comité peut être sélectionné pour un bénévole (l'HABTM est pour les besoins futurs prévus).Données HABTM endommagées pendant __saveMulti()?

Les premiers résultats montrent que la sélection de l'option BOARDOFDIRECTORS fonctionne comme prévu, mais pas les autres. Retraçant l'exécution par le code de base me conduit à Model->__saveMulti() où, Line 1393, ce code est exécuté:

$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id; 

Si je vide $data avant que le code, la sortie est FAIRASSOCIATES. Immédiatement après, sa valeur est 4AIRASSOCIATES. Il semble raisonnable de supposer que c'est la raison pour laquelle la relation n'est pas sauvegardée, mais je n'ai pas compris pourquoi les données changent à ce stade de l'exécution.

Est-ce que quelqu'un d'autre a déjà vu ça? Ai-je manqué une pièce critique? Au meilleur de ma connaissance, cela fonctionnait bien dans la version 1.2.1 (j'ai mis à jour il y a une semaine environ).

MISE À JOUR

Le premier bit de apparente bizarreries que je vois est que, bien que mon $row est une chaîne, la condition Line 1366 évalue à true donc je laisse tomber dans ce bloc de code. Si mes données sont une chaîne, comment peut-elle avoir une valeur de membre?

MISE À JOUR

J'ai clairement une réflexion à faire, mais voici la ligne de fond. Si je laisse tomber journal écrit immédiatement avant et immédiatement après Line 1394 comme ceci:

$this->log('Setting ' . $data . '[' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] . '] = ' . $id, LOG_DEBUG); 

$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id; 

$this->log('Creating ' . json_encode($data) . ' on ' . $join, LOG_DEBUG); 

La sortie correspondante est:

2010-03-05 18:57:08 Debug: Setting FAIRASSOCIATES[volunteer_id] = 4b78717f-8ad4-4671-b81c-4e8745591fb4 
2010-03-05 18:57:08 Debug: Creating "4AIRASSOCIATES" on CommitteesVolunteer 

Problèmes possibles:

  1. Je ne sais pas comment/pourquoi Gâteau essaie de mettre le membre volunteer_id sur une chaîne
  2. "FAIRASSOCIATES" est l'ID d'un comité auquel un volontaire er est groupé, pas un modèle d'aucune sorte, donc je ne comprends pas la pertinence de FAIRASSOCIATES[volunteer_id] du tout.
  3. Je ne sais pas comment ou pourquoi la valeur de $data est transformée en 4AIRASSOCIATES par cette ligne de code.

Répondre

0

Il semble que mon problème soit causé par quelque chose de non conventionnel.Pour les tables de recherche dont les valeurs changent rarement (et il n'est pas prévu de le faire via l'application), j'aime que les valeurs de PK soient lisibles par l'homme. Cela me permet d'examiner les données directement dans la base de données et de lire de manière significative un enregistrement connexe. Dans ce cas, je peux regarder un enregistrement Volunteer et, sans exiger aucune sorte de jointure, voir qu'il/elle est dans le Committee nommé FAIRCOMMITTEE. Un peu pratique lorsque vous regardez les données en dehors de l'application.

Dans ce cas, l'une de mes 3 valeurs Committee est simplement composée de 16 caractères - une longueur CakePHP interprétée comme un UUID - donc elle s'est comportée correctement. Les autres ne comportent pas 16 caractères et ne se sont pas comportés correctement.

La condition qui échoue est Line 1355. J'ai entré a ticket pour voir s'il y a une marge d'amélioration dans l'intelligence de détection UUID.

1

J'ai écrit un petit correctif et il est en TEST, (atm ça marche): il remplace la détection uuid (SI stupide demande juste si les données ont 16 longueur ou 32 longueur) et suppose que c'est un id valide s'il est une chaîne ou un nombre pour les données entrées.

ajoutez simplement la fonction (copier l'ensemble de la fonction):

fonction

__saveMulti ($ jointe, $ id)

Du model.php de lib au app_model.php de votre application

Ensuite, remplacez le IF précédemment dans la ligne model.php 1355:

si ((is_string ($ row) & & (strlen ($ row) == 36 || strlen ($ row) == 16)) || is_numeric ($ row)) {

dès maintenant votre app_model.php pour celui-ci (ne pas modifier le model.php de votre lib, faites ceci dans votre app_model.php):

if ((is_string ($ row) & & ((strlen ($ row) == 36 || strlen ($ row) == 16) ||! $ this -> {$ assoc} -> autoPrimaryKey)) || (est_numérique ($ row))) {

puis dans votre app_model.php ajouter cette variable:

var $autoPrimaryKey = true; 

et dans les modèles que vous souhaitez ce comportement ajouter la même variable mais fausse, il Asume que le modèle ne marche pas avoir généré automatiquement UUID pour HABTM et résoudre le problème

var $autoPrimaryKey = false; 

Je répète c'est juste une solution dans les tests, il a résolu le problème pour moi, toute question que vous avez, envoyez-le à mon mail zydriel AT gmail.com

+0

Belle solution, Jose. Mon intention a été de contourner cela de la même manière, mais je n'avais pas décidé d'une approche. Cela semble bon en attendant des tests approfondis. –