我正在尝试实施基于https://github.com/josegonzalez/cakephp-keyvalue
的键/值行为我的行为将为表单提交中的每个新密钥在数据库中插入新行,而不管密钥数量如何,如果在KeyValue表中找到user_id和key,则更新现有记录。我已经将用户模型与KeyValue模型以及行为联系起来。
当数据库没有user_id / key的记录时,它将正确插入新记录。但是我发现,如果我尝试更新同一用户的现有键值对,前两个值将正确更新,但提交的最后一个值将产生新记录。
经过一些调查后,我发现在beforeSave()
的保存循环中,即使我在beforeSave()
中使用$Model->id
为模型分配ID,然后返回true,也不会传递到Model->save()
班。
我正在使用cake 2.5.4
beforeSave中的 Model->id
未传递到Model->save()
中的lib/Model/Model.php:# 1841
if ($count > 0) {
$cache = $this->_prepareUpdateFields(array_combine($fields, $values));
**pr($this->id); //this value is empty**
if (!empty($this->id)) {
$this->__safeUpdateMode = true;
try {
$success = (bool)$db->update($this, $fields, $values);
} catch (Exception $e) {
$this->__safeUpdateMode = false;
throw $e;
}
$this->__safeUpdateMode = false;
}
KeyValueBehavior:
public function beforeSave(Model $Model, $options = array()) {
extract($this->options[$Model->alias]);
$keys = array_keys($Model->data[$Model->alias]);
$data = $Model->data;
if (in_array($fields['key'], $keys) && in_array($fields['value'], $keys)) {
return true;
}
if (isset($data[$Model->alias]) && ! empty($data[$Model->alias])) {
$dataTemplate = array($Model->alias => array());
foreach ($data[$Model->alias] as $field => $value) {
if ($Model->hasField($field)) {
$dataTemplate[$Model->alias][$field] = $value;
unset($data[$Model->alias][$field]);
}
}
$index = 0;
foreach ($data[$Model->alias] as $key => $value) {
$index ++;
$insert = $dataTemplate;
$insert[$Model->alias][$fields['key']] = $key;
if ($uniqueKeys) {
$Model->deleteAll(reset($insert));
}
$insert[$Model->alias][$fields['value']] = $value;
//check existing key value
$belongsTo = reset($Model->belongsTo);
$existing = $Model->find('first', array(
'conditions' => array(
$belongsTo['foreignKey'] => $insert[$Model->alias][$belongsTo['foreignKey']],
$fields['key'] => $insert[$Model->alias][$fields['key']]
)
));
$Model->create();
if(sizeof($existing) > 0){
$existingKV = reset($existing);
//pr($existingKV);
$Model->read(null, $existingKV['id']);
}
if ($index == count($data[$Model->alias])) {
// Even if Model->id is set here, it will not be passed to Model->save()
$Model->id = $existingKV['id'];
$Model->data = $insert;
pr($Model); // Model->id is set here but not in Model->save()
return true;
} else {
pr($insert); //Updates correctly
if (false === $Model->save($insert)) {
return false;
}
}
}
}
UsersController:
public function test() {
if ($this->request->is('post')) {
$this->Userdetail->create();
$this->request->data['Userdetail']['user_id'] = $this->Auth->user('id');
if ($this->Userdetail->save($this->request->data)) {
$this->Session->setFlash(__('The Userdetail has been saved'));
// $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The Userdetail could not be saved. Please, try again.'));
}
}
$users = $this->Userdetail->User->find('list');
$this->set(compact('users'));
}
然后我在View View / Users / test.ctp中有三个示例字段:
<?php
echo $this->Form->create('Userdetail');
echo $this->Form->input('field1');
echo $this->Form->input('field2');
echo $this->Form->input('field3');
echo $this->Form->end('submit');
要解决此问题,我在beforeSave()
的模型中添加了另一个名为“id_holder”的键,并编辑了Model/Model.php
。但最终我不想编辑CakePHP核心。
修改:使用新的saveKeyValues()
方法:
public function saveKeyValues(Model $Model, $data){
if($Model == null || $data == null){
return false;
}
if (isset($data[$Model->alias]) && ! empty($data[$Model->alias])) {
$dataTemplate = array($Model->alias => array());
foreach ($data[$Model->alias] as $field => $value) {
if ($Model->hasField($field)) {
$dataTemplate[$Model->alias][$field] = $value;
unset($data[$Model->alias][$field]);
}
}
}
$belongsTo = reset($Model->belongsTo);
$index = 0;
foreach ($data[$Model->alias] as $key => $value) {
$index++;
$insert = $dataTemplate;
$insert[$Model->alias][$this->options[$Model->alias]['fields']['key']] = $key;
$insert[$Model->alias][$this->options[$Model->alias]['fields']['value']] = $value;
$insert[$Model->alias][$belongsTo['foreignKey']] = $data[$belongsTo['foreignKey']];
//check existing key value
$existing = $Model->find('first', array(
'conditions' => array(
$belongsTo['foreignKey'] => $data[$belongsTo['foreignKey']],
$this->options[$Model->alias]['fields']['key'] => $key
)
));
//Reset for create/update
$Model->create();
if(sizeof($existing) > 0){
$existingKV = reset($existing);
$Model->read(null, $existingKV['id']);
}
if (false === $Model->save($insert)) {
return false;
}
if($index == count($data[$Model->alias])){
return true;
}
}
}