Сохранение нескольких записей для одной модели в CakePHP

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

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

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

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

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

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

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

4 ответов


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

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

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

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

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);

и это торт способ сделать это!


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

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

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


вы собираетесь массировать формы выходной костюм 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, но обрабатывает специальные случаи сам.


возможно, есть более простой способ сделать это, но я использовал такую технику: во-первых, измените форму, чтобы вы получили такой массив:

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

(просто измените имя многозначного ввода на selected_users.id)

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

foreach( $this->data[ 'selected_users' ][ 'id' ] as $userId ) {
    $this->data[ 'Notification' ][ 'user_id' ] = $userId;
    $this->Notification->create();  // initializes a new instance
    $this->Notification->save( $this->data );
}