我在修改保存其中一个关联表的逻辑时遇到问题。 这两个表是:
在客户端控制器中,方法edit(),classic,用cakephp烘焙,另外还有关联的表:
$client = $this->Clients->get($id, [
'contain' => ['ClientMetadatas']
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$client = $this->Clients->patchEntity($client, $this->request->data);
if ($this->Clients->save($client, ['associated' => ['ClientMetadatas']])) {
$this->Flash->success(__('The client has been saved.'));
} else {
$this->Flash->error(__('The client could not be saved. Please, try again.'));
$this->response->statusCode(500);
$client=$client->errors();
}
}
$this->set(compact('client'));
$this->set('_serialize', ['client']);
我编辑客户端及其元数据的一个示例是,调用' / clients / edit / clientid .json'
{
"firstname": "John",
"firstname": "Smith",
"client_metadatas":
[
{
"name": "test",
"value": "test"
}
]
}
以下是我的问题:我想验证此client_id和元数据的名称是否不存在元数据。如果存在,我执行更新而不是插入。
似乎理想的解决方案是直接在模型中完成。
我尝试使用回调方法:
有关如何在保存实体之前正确执行验证和插入/更新之间切换的任何建议吗?
PS:我希望没有丢失的信息。如果是这样,请不要犹豫,我会添加它们......谢谢!
答案 0 :(得分:1)
CakePHPs ORM可以自己开箱即用。是否正在执行更新或插入,是基于要保存的实体的持久性状态,即基于Entity::isNew()
的返回值。
来自Table::save()
API文档的引用:
此方法将确定是否需要在数据库中插入或更新传递的实体。它通过检查实体上的
isNew
方法来实现。
为了自动正确设置,您必须在数据中提供这些记录的可能现有主键值,以便编组可以在修补请求数据时正确准备实体。
因此,在您准备数据时,请确保包含主键值(如果存在),以便您发送以下内容:
{
"firstname": "John",
"firstname": "Smith",
"client_metadatas":
[
{
"id": 1,
"name": "existing",
"value": "existing"
},
{
"name": "non-existing",
"value": "non-existing"
}
]
}
第一组是更新(假设存在具有id
主键值的记录),第二组将是插入。
当然,也可以自己处理事情,即不传递请求数据中的主键值,至少只要有另一个唯一列。搜索其他自定义标准(如记录名称),然后相应地修改实体以便更新相应的行,应该可以正常工作。
您可以在beforeSave
回调/事件中,甚至在beforeMarshall
回调/事件中执行此操作,具体取决于您要应用此功能的时间,具体内容如下:
public function beforeSave(
\Cake\Event\Event $event,
\Cake\Datasource\EntityInterface $entity,
\ArrayObject $options
)
{
if ($entity->isNew()) {
$existing = $this
->find()
->where([
'name' => $entity->get('name')
])
->first();
if ($existing) {
$entity->set('id', $existing->get('id'));
$entity->isNew(false);
}
}
return true;
}