doulan6245
2017-02-21 18:38
浏览 14
已采纳

CakePhp 3:在键值表中插入/更新相关字段之间切换

I'm having trouble modifying the logic for saving one of my associated table. The two tables are:

  • Clients
  • ClientMetadatas (storing the client's metadata with key/value pairs)

In the Clients Controller, the method edit(), classic, baked with cakephp, with the associated table in addition:

    $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']);

An example of how I edit a client and its metadatas would be, calling '/clients/edit/clientid.json'

{
        "firstname": "John",
        "firstname": "Smith",
        "client_metadatas": 
        [
            {
                "name": "test",
                "value": "test"
            }
        ]
}

Here's my problem: I'd like to verify if there is no metadata existing with this client_id and metadata's name. If it exists, I'd perform an update rather than an insert.

It seems that the ideal solution would be to do it in the Model directly.

I tried to use the callback methods:

  • beforeSave(), but I wasn't able to modify the entity
  • beforeFind(), but I wasn't able to modify the query

Any advice on how to properly do the verification and the switch between insert/update before saving the entity?

PS: I hope no information in missing. If it the case, don't hesitate, I'll add them...

Thank you !

图片转代码服务由CSDN问答提供 功能建议

我在修改保存其中一个关联表的逻辑时遇到问题。 这两个表是:

  • 客户端
  • ClientMetadatas(使用键/值对存储客户端的元数据)

    在客户端控制器中,方法edit(),classic,用cakephp烘焙,另外还有关联的表:

      $  client = $ this-> Clients-> get($ id,[
    '包含'=> ['ClientMetadatas'] 
    ]);  
    如果($ this-> request->是(['patch','post','put'])){
     $ client = $ this-> Clients-> patchEntity($ client,  $ this-> request-> data); 
     if($ this-> Clients-> save($ client,['associated'=> ['ClientMetadatas']])){
     $ this  - > Flash->成功(__('客户端已保存。')); 
    } else {
     $ this-> Flash->错误(__('客户端无法保存。 请再试一次。')); 
     $ this-> response-> statusCode(500); 
     $ client = $ client-> errors(); 
    } 
    } 
     $ this-  > set(compact('client')); 
     $ this-> set('_ serialize',['client']); 
       
     
     

    我如何编辑客户端及其元数据的示例,调用'/clients/edit/clientid.json'

    nn
     {
    “firstname  “:”John“,
    ”firstname“:”Smith“,
    ”client_metadatas“:
     [
     {
    ”name“:”test“,
    ”value“:”test“
    }  
      ] 
    } 
       
     
     

    这是我的问题:我想验证此client_id和元数据的名称是否没有元数据。 如果它存在,我将执行更新而不是插入。

    似乎理想的解决方案是直接在模型中执行。

    我尝试使用回调方法:

    • beforeSave(),但我无法修改实体
    • beforeFind(),但我无法修改查询

      有关如何正确执行验证以及在保存之前切换/更新之间切换的任何建议 实体?

      PS:我希望没有丢失的信息。 如果是这样,请不要犹豫,我会添加它们......

      谢谢!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongtang3155 2017-02-21 19:15
    已采纳

    Insert/update determination works out of the box

    CakePHPs ORM can do that on its own out of the box. Whether an update or an insert is being performed, is figured based on the persistence status of the entity that is to be saved, ie based on the return value of Entity::isNew().

    Quote from the Table::save() API docs:

    This method will determine whether the passed entity needs to be inserted or updated in the database. It does that by checking the isNew method on the entity.

    Primary key values need to be present

    In order to have this being set up properly automatically, you have to provide the possible existing primary key values of those records in your data, so that the marshaller can prepare the entities properly when patching in the request data.

    So where/however you are preparing that data, make sure that you include the primary key value(s) in case they exist, so that you send something like this:

    {
        "firstname": "John",
        "firstname": "Smith",
        "client_metadatas": 
        [
            {
                "id": 1,
                "name": "existing",
                "value": "existing"
            },
            {
                "name": "non-existing",
                "value": "non-existing"
            }
        ]
    }
    

    The first set would be an update (given that a record with such an id primary key value exists), the second one would be an insert.

    Find existing records based on custom criteria

    Surely it's also possible to handle things on your own, ie without passing the primary key values in the request data, at least as long as there is another unique column. Searching for other, custom criterias, like the name of the record, and then modifying the entity accordingly so that the respective row is being updated, should work fine.

    You could do that in the beforeSave callback/event, or even in the beforeMarshall callback/event, depending on when you want to this to apply, something along the lines of:

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

    See also

    点赞 打赏 评论

相关推荐 更多相似问题