CakePHP HABTM: редактирование одного элемента вызывает строку HABTM для воссоздания, уничтожает дополнительные данные - PullRequest
1 голос
/ 16 февраля 2010

У меня проблемы с отношениями с 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, когда я просто редактирую поле в строке? Это даже не внешний ключ!

Ответы [ 3 ]

1 голос
/ 16 февраля 2010

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

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

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

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

1 голос
/ 16 февраля 2010

Из поваренной книги 1-я проблема:

По умолчанию при сохранении HasAndBelongsToMany отношения, торт удалит все строки в соединительной таблице перед сохранением новых.

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

$this->Location->unbindModel(
    array('hasAndBelongsToMany' => array('Department'))
);
0 голосов
/ 04 мая 2010

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

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

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

...