Сохранить несколько записей для одной модели в CakePHP - PullRequest
6 голосов
/ 23 ноября 2010

Я хотел бы сохранить несколько записей для одной модели. Это было бы довольно легко сделать с saveAll(), если бы не проблема:

У меня есть форма уведомления, в которой я выбираю несколько пользователей из <select> и двух полей для темы и контента соответственно. Теперь, когда я вывожу то, что содержит $this->data, у меня есть:

Array([Notification] => Array
    (
        [user_id] => Array
            (
                [0] => 4
                [1] => 6
            )

        [subject] => subject
        [content] => the-content-here
    )
)

Я прочитал в книге Cake 1.3, что для сохранения нескольких записей для модели вам нужно иметь $this->data что-то вроде:

Array([Article] => Array(
        [0] => Array
            (
                        [title] => title 1
                    )
        [1] => Array
            (
                        [title] => title 2
                    )
            )
)

Итак, как мне «поделиться» темой и контентом со всеми выбранными пользователями?

Ответы [ 4 ]

6 голосов
/ 26 ноября 2010

Прежде всего, этот дизайн базы данных должен быть нормализован.

Мне кажется, что Notification может иметь много User s, связанных с ним.В то же время, User может иметь много Notification с.Следовательно,

  • Представьте таблицу соединений с именем users_notifications.
  • Реализация отношения HABTM: Уведомление hasAndBelongsToMany Пользователь

В представленииВы можете просто использовать следующий код для автоматического вызова формы множественного выбора для получения идентификаторов пользователей:

echo $this->Form->input('User');

Данные, отправляемые на контроллер, будут иметь форму:

Array(
    [Notification] => Array
        (
            [subject] => subject
            [content] => contentcontentcontentcontentcontentcontent
        ),
    [User] => Array
        (
            [User] => Array
                (
                    [0] => 4
                    [1] => 6
                )
         )
)

Теперь все, что вам нужно сделать, это вызвать функцию saveAll () вместо save ().

$this->Notification->saveAll($this->data);

И это способ Cake сделать это!

6 голосов
/ 23 ноября 2010

Эти значения должны повторяться следующим образом

Array([Notification] => Array(
        [0] => Array
            (
                        [user_id] => 4
                        [subject] => subjects
                        [content] => content
                    )
        [1] => Array
            (
                        [user_id] => 6
                        [subject] => subject
                        [content] => contents
                    )
            )
)


$this->Notification->saveAll($data['Notification']); // should work

Если вы не передадите значение столбца, этот торт просто проигнорирует его

4 голосов
/ 23 ноября 2010

Вам придется помассировать вывод вашей формы, чтобы удовлетворить Model::saveAll. В вашем контроллере:

function action_name()
{
    if ($this->data) {

        if ($this->Notification->saveMany($this->data)) {
            // success! :-)
        } else {
            // failure :-(
        }
    }
}

А в вашей модели:

function saveMany($data)
{
    $saveable = array('Notification'=>array());

    foreach ($data['Notification']['user_id'] as $user_id) {

        $saveable['Notification'][] = Set::merge($data['Notification'], array('user_id' => $user_id));
    }

    return $this->saveAll($saveable);
}

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

На самом деле, вы, вероятно, могли бы переопределить saveAll в своей модели, которая переводит правильно отформатированные входные массивы в parent::saveAll, но сама обрабатывает особые случаи.

1 голос
/ 23 ноября 2010

Возможно, есть более простой способ сделать это, но я использовал такую ​​технику: во-первых, измените форму так, чтобы вы получили массив, подобный следующему:имя входного элемента множественного выбора к selected_users.id)

Затем выполните цикл по идентификаторам пользователя и сохраните каждую запись отдельно:

...