CakePHP HABTM: Modification d'un élément casuses ligne HABTM pour obtenir recréée, détruit des données supplémentaires

StackOverflow https://stackoverflow.com/questions/2275353

Question

Je vais avoir du mal à ma relation HABTM dans CakePHP.

J'ai deux modèles comme ceci: Department HABTM Location. Une grande entreprise possède de nombreux bâtiments, et chaque bâtiment offre un nombre limité de services. Chaque bâtiment a aussi sa propre page web, donc en plus de la relation HABTM lui-même, chaque rangée de HABTM dispose également d'un champ url où l'utilisateur peut visiter pour trouver des informations supplémentaires sur le service qu'ils sont intéressés et comment elle fonctionne à l'immeuble qu'ils » intéresse.

J'ai mis en place les modèles comme ceci:

<?php
class Location extends AppModel {
    var $name = 'Location';

    var $hasAndBelongsToMany = array(
        'Department' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>


<?php
class Department extends AppModel {
    var $name = 'Department';

    var $hasAndBelongsToMany = array(
        'Location' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>

<?php
class DepartmentsLocation extends AppModel {
    var $name = 'DepartmentsLocation';

    var $belongsTo = array(
        'Department',
        'Location'
    );    


    // I'm pretty sure this method is unrelated. It's not being called when this error
    // occurs. Its purpose is to prevent having two HABTM rows with the same location
    // and department.
    function beforeSave() {

        // kill any existing rows with same associations
        $this->log(__FILE__ . ": killing existing HABTM rows", LOG_DEBUG);

        $result = $this->find('all', array("conditions" =>
            array("location_id" => $this->data['DepartmentsLocation']['location_id'],
                  "department_id" => $this->data['DepartmentsLocation']['department_id'])));


        foreach($result as $row) { 
            $this->delete($row['DepartmentsLocation']['id']);
        }

        return true;
    }
}
?>

Les contrôleurs sont totalement sans intérêt.

Le problème: Si je modifier le nom d'un Location, tous les DepartmentsLocations qui ont été liés à cette Location sont recréés avec des URL vides. Étant donné que les modèles spécifient qu'unique est vrai, cela provoque aussi toutes les lignes nouvelles pour remplacer les lignes anciennes, qui détruit la quasi-totalité des URL.

Je voudrais savoir deux choses: Puis-je arrêter cela? Si oui, comment?

Et, sur une note moins technique et plus whiney: Pourquoi cela ne se produit même? Il me semble bizarre que l'édition d'un champ par gâteau devrait causer tant de peine, quand je peux facilement passer par phpMyAdmin, modifiez le nom de Location là-bas, et obtenir exactement le résultat que je me attends. Pourquoi CakePHP toucher les données HABTM quand je suis juste un champ d'édition sur une ligne? Il est même pas une clé étrangère!

Était-ce utile?

La solution

De CookBook 1er problème est:

  

Par défaut lors de l'enregistrement d'une   relation HasAndBelongsToMany, gâteau   effacera toutes les lignes sur la table de jointure   avant d'enregistrer de nouveaux.

Je ne suis pas tout à fait sûr pourquoi gâteau tente de sauver les données HABTM même si vous ne disposez pas d'une clé étrangère dans vos données, mais il y a une solution facile pour cela. Il suffit de détruire l'association pour la Enregistrer le numéro:

$this->Location->unbindModel(
    array('hasAndBelongsToMany' => array('Department'))
);

Autres conseils

Je pense à l'une des raisons pour lesquelles cela pourrait se produire. Lorsque vous récupérez Location, vous récupérez également des données locations_departments. Et quand vous faites un save($this->data) il recherche des modèles dans le tableau et les enregistre.

Une façon de résoudre ce problème est définissant l'attribut recursive (d'un modèle) -1 ou 0 (essayer, je ne suis pas sûr, imprimez la données pour voir ce qui sort). Vous pouvez le configurer dans le modèle: var $recursive = -1; ou dans la méthode de commande (action): $this->ModelName->recursive = -1;

En savoir plus sur récursive: http://book.cakephp.org/view/439/recursive

Il est vraiment semblable à ce que Harpax suggérez, juste si vous n'avez pas besoin de ces données, dites à gâteau, de sorte qu'il ne sera pas le chercher.

Le problème est que lorsque vous enregistrez votre Location, vous avez donné la méthode de sauvegarde un tableau contenant toutes les DepartmentsLocations aussi. Ainsi CakePHP détruit tout et essayer de le recréer.

Ceci est une erreur commune avec un gâteau car il sera souvent tirer beaucoup trop de résultats pour vous.

Assurez-vous de transmettre uniquement les données qui doit être sauvé, ou mieux récupérer uniquement les données dont vous avez besoin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top