在CakePHP中为一个模型保存多条记录

问题描述:

我想为一个模型保存多条记录。这已经与saveAll()做得相当容易,如果它不是为一个问题:在CakePHP中为一个模型保存多条记录

我有一个通知的形式,在这里我选择分别从<select>和两个字段中的多个用户,主题和内容。现在,当我输出什么$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 
        ) 
      ) 
) 

那么,我如何将主题和内容“分享”给所有选定的用户呢?

首先,这个数据库设计需要正常化。

在我看来,像一个Notification可以有很多User与它有关。同时,User可以有许多Notification。因此,

  • 引入名为users_notifications的连接表。
  • 落实HABTM关系:通知hasAndBelongsToMany用户

在视图中,可以简单地使用下面的代码来自动地弹出多选的形式抢用户ID:

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的方法!

有可能是这样做的更加cakey方式,但我已经使用这种技术:首先,改变形式,让你得到一个这样的数组:

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

(只要改变多选输入的名字selected_users.id)

然后通过用户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); 
} 
+0

谢谢你的回答。我认为这是一个更加“干脆”的方法。但是,我会采取“直截了当”的方式。 – linkyndy 2010-11-23 20:41:44

这些值必须重复这样

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 

如果不传递任何列值,这个蛋糕会忽略它

+0

谢谢你的回答! – linkyndy 2010-11-23 20:48:56

你将有按摩你的表单输出,以满足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,但本身处理特殊情况。

+0

谢谢你的回复。做一个单独的方法是一个很好的建议,会做到这一点! – linkyndy 2010-11-23 20:48:15

+0

将此封装到模型012为+1 – Ish 2010-11-23 21:09:56