CakePHP 2.X: запретить saveAssociated() создавать запись, если она уже существует
У меня есть следующие модели:
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()
если запись существует не работает, так как ничего не сохраняется. - Замена
Useragent['id']
вUseragent::beforeSave()
сid
из существующей записи, полученной из базы данных, не будет проверяться. Удаление правила проверки приведет кIntegrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'
,
Возможность переопределить Useragent::save()
метод, так что он игнорирует операцию сохранения, но устанавливает Useragent->id
к id
записи, извлеченной из базы данных и возвращающей массив (как при обычном сохранении), но не уверен, что это нарушит другие функции.
Другой вариант - написать метод с именем LoggedAction::saveWithUseragent()
, который будет реализовывать описанную функциональность. Но, как я уже сказал, я хотел бы модель Useragent
позаботиться об этом как можно более прозрачно.
Есть ли лучший способ реализовать это, что мне не хватает?
1 ответ
Я наконец решил переопределить 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);
}
}
Пока проблем нет.
Тот же подход можно использовать для тегов, связанных с другими моделями.