0

我有以下型号:

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模型忽略保存(仅基于字段,而不是执行保存时未知的字段)。useragentsUseragent.useragentUseragent.id

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

  • 如果记录存在则返回 falseUseragent::beforeSave()不起作用,因为没有保存任何内容。
  • 用从数据库中获取的现有记录替换,将无法Useragent['id']验证。删除验证规则将抛出.Useragent::beforeSave()idIntegrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'

一个选项是覆盖该Useragent::save()方法,以便它忽略保存操作,但将 设置Useragent->idid从数据库中获取的记录并返回数组(就像普通保存一样),但不确定这是否会破坏其他功能.

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

有没有更好的方法来实现我所缺少的?

4

1 回答 1

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);
    }
}

到目前为止没有问题。

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

于 2015-12-11T16:52:22.303 回答