Сохранение записей HABTM, когда не все столбцы таблицы соединения являются внешними ключами - PullRequest
0 голосов
/ 17 февраля 2009

Я пытаюсь обновить таблицы с отношением has и принадлежит многим (HABTM).

Когда моя таблица соединений выглядела так:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Я использую CakePHP, чтобы я мог обновить таблицы с помощью $ this-> Item-> save ($ data), где $ data:

Array
(
    [Item] => Array
        (
            [id] => 1
        )
    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => 4
                    [1] => 5
                    [2] => 7
                    [3] => 8
                )
        )
)

Я добавил столбец в свою таблицу соединений, теперь он выглядит следующим образом:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Когда я сохраняю $ data, я также хочу сохранить идентификатор пользователя. Идентификатор пользователя будет одинаковым для всех записей в одной операции сохранения.

Может кто-нибудь помочь мне понять, как должен выглядеть массив $ data для включения идентификатора пользователя? Спасибо.

Ответы [ 2 ]

2 голосов
/ 19 февраля 2009

Это должно работать:

Array
(
    [Item] => Array
        (
            [id] => 1
        )

    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => Array
                        (
                            [label_id] => 4
                            [user_id] => 1
                        )

                    [1] => Array
                        (
                            [label_id] => 5
                            [user_id] => 1
                        )

                    [2] => Array
                        (
                            [label_id] => 7
                            [user_id] => 1
                        )

                    [3] => Array
                        (
                            [label_id] => 8
                            [user_id] => 1
                        )

                )

        )

)

Он сгенерирует несколько INSERT, но будет работать с одним вызовом сохранения.

1 голос
/ 19 февраля 2009

Метод model :: save () CakePHP не сделает это за вас, AFAIK. Я думаю, что вы должны использовать model :: saveAll () и вызывать его для модели «with». CakePHP автоматически знает вашу таблицу соединений и может ее смоделировать, не создавая файл физической модели и не проводя класс самостоятельно. Все, что вам нужно сделать, это отформатировать массив данных в формате, который ожидает saveAll.

Я не пробовал, но должно работать что-то вроде следующего.

<?php
class Item extends AppModel {
  var $name = 'Item';
  var $_habtmData = null;
  function beforeSave() {
    $this->unbindModel(array('hasAndBelongsToMany' => array('Label')));
    $this->_habtmData = $this->data['Label'];
  }
  function afterSave() {
    if (is_array($this->_habtmData) && !empty($this->_habtmData)) {
      foreach ($this->_habtmData['Label'] as $k => $labelId) {
        $this->_habtmData['Label'][$k] = array(
          'item_id' => $this->id,
          'label_id' => $labelId,
          'user_id' => $userId, // Get this from somewhere
        );
      }
      $this->bindModel(array('hasMany' => array('ItemsLabel')));
      $this->ItemsLabel->saveAll($this->_habtmData);
    }
  }
}
?>

Это все сделано в модели (как и должно быть), поэтому ваш контроллер и представления остаются чистыми. Мы делаем все это в afterSave, поэтому он пробует это только в случае проверки данных Item.

По сути, мы временно отсоединяем привязку Item hasAndBelongsToMany Label в beforeSave, поэтому данные HABTM не сохраняются, и мы сохраняем данные HABTM в свойстве модели, поэтому мы можем использовать их в afterSave (хотя, вероятно, все еще в любом случае доступно).

Затем мы связываем модель «с» с Item с помощью ассоциации hasMany и форматируем данные в соответствии с требованиями метода core model :: saveAll () в CakePHP, прежде чем, наконец, вызвать его в модели «с», передав новую данные.

Это должно сработать в теории - удачи, и дайте мне знать, как вы поживаете; -)

...