CakePHP HABTM:Редактирование одного элемента приводит к воссозданию строки HABTM, уничтожающей дополнительные данные

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

Вопрос

У меня возникли проблемы с моими отношениями HABTM в CakePHP.

У меня есть две такие модели: Department HABTM Location.У одной крупной компании много зданий, и каждое здание предоставляет ограниченное количество услуг.Каждое здание также имеет свою собственную веб-страницу, поэтому в дополнение к самой связи HABTM, каждая строка HABTM также имеет url поле, которое пользователь может посетить, чтобы найти дополнительную информацию об интересующей его услуге и о том, как она работает в интересующем его здании.

Я настроил модели следующим образом:

<?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;
    }
}
?>

Контроллеры совершенно неинтересны.

В чем проблема: Если я отредактирую имя Location, все из DepartmentsLocationы, которые были связаны с этим Location создаются заново с пустыми URL-адресами.Поскольку в моделях указано, что значение unique равно true , это также приводит к тому, что все новые строки перезаписывают старые строки, что по существу уничтожает все URL-адреса.

Я хотел бы знать две вещи:Могу ли я прекратить это?Если да, то каким образом?

И на менее технической и более плаксивой ноте:Почему это вообще происходит?Мне кажется странным, что редактирование поля через Cake должно вызывать так много проблем, когда я могу легко пройти через phpMyAdmin, отредактировать Location назовите там имя и получите именно тот результат, который я ожидал.Почему CakePHP затрагивает данные HABTM, когда я просто редактирую поле в строке?Это даже не внешний ключ!

Это было полезно?

Решение

Из кулинарной книги следует, что 1-я проблема заключается в следующем:

По умолчанию при сохранении отношения Has и belongsToMany, Cake удалит все строки в таблице объединения перед сохранением новых.

Я не совсем уверен, почему Cake пытается сохранить данные HABTM, даже если у вас нет внешнего ключа в ваших данных, но для этого есть простое решение.Просто уничтожьте ассоциацию для вызова сохранения:

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

Другие советы

Я думаю об одной причине, почему это может происходить.Когда вы получаете Location, вы также получаете locations_departments данные.И когда вы делаете save($this->data) он ищет модели в массиве и сохраняет их.

Способ решения этой проблемы — установка recursive атрибут (модели) -1 или 0 (попробуйте, я не уверен, просто распечатайте данные и посмотрите, что получится).Вы можете установить его в модели: var $recursive = -1; или в методе контроллера (действии): $this->ModelName->recursive = -1;

Подробнее о рекурсивном: http://book.cakephp.org/view/439/recursive

Это действительно похоже на то, что гарпакс предложил, просто если вам не нужны эти данные, сообщите об этом Cake, чтобы он не получил их.

Проблема в том, что при сохранении Location, вы передали методу сохранения массив, содержащий все DepartmentsLocations слишком.Таким образом CakePHP уничтожает все и пытается воссоздать это.

Это распространенная ошибка с тортом, поскольку он часто приносит слишком много результатов.

Обязательно передавайте только те данные, которые необходимо сохранить, или лучше получить только те данные, которые вам нужны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top