Сохранение записей HABTM, когда не все столбцы таблицы объединения являются внешними ключами

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

Вопрос

Я пытаюсь обновить таблицы с помощью отношения "имеет" и "принадлежит многим" (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, чтобы включить идентификатор пользователя?Спасибо.

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

Решение

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

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
                        )

                )

        )

)

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

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

Метод CakePHP model::save(), 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 Has и belongsToMany в beforeSave, поэтому данные HABTM не сохраняются, и мы сохраняем данные HABTM в свойстве модели, чтобы мы могли использовать их в afterSave (хотя, вероятно, они все еще доступны в любом случае).

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

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

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