Save to two tables (protection error)

I have two tables, Documents and Logs, I want to save bulk items to Documents and at the same time I want to save one row to the Logs table. If something cannot be written to either the Documents or Logs table, then the data should not be written to any table.

What should the code look like, please? Use transactions? Or something else?

When you have an entity with associated entities in it, saving it does exactly this. So, if you have a $document, and $document->log is the log entity, then a transaction will automatically be used when you ->save($document).

I used:

$Content = $this->UsersDocuments->patchEntities($Content, $data);

$this->UsersDocuments->saveMany($Content)

The Logs has no more entities, only one.

$log = $this->Logs->newEmptyEntity();
$log = $this->Logs->patchEntity($log, $data);

$this->Logs->save($log);

Do I have to combine? save and saveMany ?

As I said, your “primary” entity (seems you’ve got an array of them in $Content here?) needs to have a Log entity in it. Hard to give a concrete example without knowing what the $data looks like. It’s presumably something different in the Logs->patchEntity call above than the UsersDocuments->patchEntities call?

$Content does not have a Log entity

  1. I edit several items in bulk, eg. 20 items
  2. then use the saveMany method to save the data.
  3. after successful saving, I want to write an event to the Logs table that the operation was successful. I will use the save method of one item insert to db.

Is there a simple example of how to build it? It doesn’t have to be accurate.

Ah, you want only a single log entry to indicate that many items were updated. Then yes, you’d want to use a transaction. There are two ways to do this; I personally always use the “transactional” callback approach, as I find it easier to get the logic right.

1 Like

Exactly.
And is there an example of using a transaction somewhere? Thank you very much

You mean other than the examples given right in the link that I provided?

Yes, use not directly SQL query, but eg

$this->Table->save( ....

You can use $table->save(...) instead of $connection->execute(...) in either of the examples in the documentation. Any operation will be fine: save, saveMany, update, delete, whatever. It all happens in the context of the transaction.

I understand. So if I want to do transactions that will contain different tables that have no association, then the example is https://book.cakephp.org/3/en/orm/database-basics.html#using-transactions and if I save with association, then use $this->Table->save(...

Essentially, yes. Anything that happens in a single call (e.g. one save) will automatically happen in a transaction (though there’s an option to turn that off). You can manually force transactions to wrap any set of calls that you want to via the options at that link.

1 Like