CakePHP 2.X:防止saveAssociated()创建记录(如果已存在)

时间:2015-11-27 11:30:51

标签: cakephp cakephp-2.7 cakephp-2.x

我有以下型号:

class Useragent extends AppModel {

    public $validate = array(
        'useragent' => array(
            'unique' => array(
                'rule' => 'isUnique',
            ),
        )
    );

    public $hasMany = array(
        'LoggedActions'
    );
}

class LoggedAction extends AppModel {

    public $belongsTo = array(
        'Useragent' => array(
            'className' => 'Useragent',
        )
    }
} 

这两个模型的目的是跟踪网站访问者的IP地址和用户代理。我希望表格被规范化,因为我不希望每一行都重复长用户代理字符串。

要跟踪访问者,代码如下:

    $data=array(
        'LoggedAction'=>array(
            'ip_address' => 3232235521, //INET_ATON format
        ),
        'Useragent'=>array(
            'useragent'=>'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'
        )
    );

    $this->LoggedAction->saveAssociated($data);

如果用户代理已存在于Useragent表格中(仅基于字段useragents,我希望Useragent.useragent模型忽略保存,不在执行保存时未知的Useragent.id上。

我知道我可以在控制器上实现这一点,首先处理Useragent然后再处理LoggedAction。但是,我希望模型能够透明地处理这个问题。

  • 如果记录存在,则在Useragent::beforeSave()中返回false不起作用,因为没有保存。
  • 使用从{db>获取的现有记录中的Useragent['id']替换Useragent::beforeSave()中的id将不会进行验证。删除验证规则将抛出Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'

选项是覆盖Useragent::save() 方法,以便忽略保存操作,但将Useragent->id设置为提取的记录的id从db返回数组(就像普通的保存一样),但不确定这是否会破坏其他功能。

另一种选择是编写一个名为LoggedAction::saveWithUseragent()的方法,它将实现所描述的功能。但正如我所说,我希望模型Useragent尽可能透明地处理这个问题。

有没有更好的实现方法,我错过了?

1 个答案:

答案 0 :(得分:0)

我最终选择覆盖Useragent::save()

这就是我的Useragent课程现在的样子:

class Useragent extends AppModel
{

    public $displayField = 'useragent';

    public $hasMany = array(
        'LoggedActions'
    );


    public function save($data = null, $validate = true, $fieldList = array()){

        if ($useragent=$this->findByUseragent($data['useragent'])){
            $this->id=$useragent[$this->alias]['id'];
            return($useragent);
        }
        return parent::save($data,$validate,$fieldList);
    }
}

到目前为止没有问题。

可以将相同的方法用于与其他模型相关联的标签。