这是我的beforeSave函数。checkExisting()检查$this->data中的某些字段是否唯一,如果没有现有记录,则返回false;如果存在,则返回现有记录的ID。此函数运行正常。
public function beforeSave(){
if ($this->checkExisting() !== false){
$this->id = $this->checkExisting();
}
return true;
}
我认为我的代码应该这样做:如果有一个现有的记录,将Model->id设置为该现有记录的id,从而强制CakePHP更新而不是插入。
这段代码实际做的是插入一条新记录,无论如何
$this->id = $this->checkExisting();对于$this->data['Model']['id'] = $this->checkExisting();, MySQL给出一个错误(主键的值重复),因为Cake仍然试图插入数据,而不是更新数据。在哪个阶段Cake决定执行插入而不是更新?beforeSave()影响这个决定是否太晚了?
编辑-这是我的控制器代码:public function add(){
if (!empty($this->data)){
$saved = 0;
foreach($this->data['Attendance'] as $att){
$this->Attendance->create();
if ($this->Attendance->save(array('Attendance'=>$att))){
$saved++;
}
if ($saved > 0){
$this->Session->setFlash('Data saved successfully','success');
}else{
$this->Session->setFlash('No data was saved. Please make sure you have entered some data.','failure');
}
}
}
}
考虑一下,这是否与我显式调用考勤::create()有关?
不,beforeSave现在更改还不算太晚。Model->save()按顺序执行以下操作:
- 调用Model->set(),传递提供的数据。提取一个id并设置Model->id
- 调用回调函数(包括beforeSave())
- 根据设置的Model->id决定是更新还是插入
假设checkExisting()行为正确,上面的代码应该可以工作。我想再检查一下你的checkExisting()代码。
还请注意,您的代码在两次调用checkExisting()时效率低下。这样会更好:
$existing = $this->checkExisting();
if($existing) {
$this->id = $existing;
}
编辑我猜您已经创建了checkExisting(),因为如果其中一条记录无效,上面的add()操作最终会保存部分记录集。您应该使用saveAll(),它可以在保存任何记录之前验证所有记录。
public function add() {
if(!empty($this->data)) {
if($this->Attendance->saveAll($this->data)) {
$this->Session->setFlash('Data saved successfully','success');
} else {
$this->Session->setFlash('No data was saved. Please make sure you have entered some data.','failure');
}
}
}
如果你的代码或Tyler的代码工作,那一定是某种奇迹。当调用beforeSave时,Cake已经进行了查询,以知道记录集是否存在,并且需要更新或插入。你无法在beforeSave中更改为Update。一个可能的解决方案是删除存在的记录集:
public function beforeSave() {
$existing = $this->checkExisting();
if($existing) {
$this->id = $existing;
$this->delete();
}
return true;
}
是否允许用户在不需要ID的情况下提交表单?通常,如果用户正在编辑一条记录,您应该已经有了ID,并且在提交表单时不需要检查它。然后,控制器中的函数将提交带有ID的记录,告诉模型它是UPDATE而不是SAVE。
听起来你可能在代码的某个地方走了捷径。你会发布你的控制器函数做保存/更新。然后我们可以提供正确的帮助。