CakePHP - 在Model-> beforeSave()中从插入更改为更新

时间:2011-04-19 17:03:12

标签: cakephp cakephp-1.3

这是我的beforeSave功能。 checkExisting()检查$ this->数据中的某些字段是否唯一,如果没有现有记录,则返回false,如果存在,则返回现有记录的ID。这个功能工作正常。

    public function beforeSave(){
    if ($this->checkExisting() !== false){
        $this->id = $this->checkExisting();
    }
    return true;
}

我认为我的代码应该做的是:如果有现有记录,请将Model-> id设置为该现有记录的ID,然后强制CakePHP更新而不是插入。

此代码实际上做的是插入新记录,无论如何。

如果我更改$ this-> id = $ this-> checkExisting(); to $ 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');
            }
        }
    }
}

考虑一下,是否与我明确调用Attendance :: create()这一事实有关?

3 个答案:

答案 0 :(得分:2)

不,之前保存还为时已晚。 Model-> save()按顺序执行以下操作:

  1. 调用Model-> set(),传递提供的数据。这会提取一个ID并设置Model-> id
  2. 调用回调函数(包括beforeSave())
  3. 决定是否根据Model-> id设置更新或插入
  4. 上面的代码应该可以正常运行,假设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');
            }
        }
    }
    

答案 1 :(得分:2)

如果您的代码或Tyler的代码有效,那么它必定是某种奇迹。当调用beforeSave时,Cake已经执行了查询以了解记录集是否存在且是否需要更新,否则为Insert。您无法在beforeSave中更改为更新。一种可能的解决方案是删除记录集(如果存在):

public function beforeSave() {
    $existing = $this->checkExisting();
    if($existing) {
        $this->id = $existing;
        $this->delete();
    }
    return true;
}

答案 2 :(得分:0)

您正在做的事情是否允许用户在不需要ID的情况下提交表单?通常,如果用户正在编辑记录,您应该已经拥有该ID,并且在提交表单时无需检查该ID。然后控制器中的函数将提交附有ID的记录,告诉模型它是UPDATE而不是SAVE。

听起来对你来说,你可能会在代码中的某些地方进行捷径。你会发布正在进行保存/更新的控制器功能吗?然后我们可以提供正确的帮助。