Сохранение нескольких записей для одной модели в 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
может быть много User
s связано с ним. В то же время User
может быть много Notification
s. Следовательно,
- введите таблицу соединений с именем 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 );
}