cakephp / docs

CakePHP CookBook
http://book.cakephp.org
Other
681 stars 2.58k forks source link

Example code for a try/catch + transaction combination #4867

Closed mo86 closed 5 years ago

mo86 commented 7 years ago

I would like to add an example code snippet to the documentation where we explain the best practise for a complex saving operation using a transaction and a try/catch block.

For example I want to do 2 inserts into different tables. But the second insert should only be done when the first insert was done without errors.

My approach:


try {
            $conn = ConnectionManager::get('default');
            //start transaction
            $conn->begin();

            $table1 = TableRegistry::get('Table1');
            $entity1 = $table1->newEntity();
            $entity1->bar = 'foo';

            //validate
            if ($entity1->errors()) {
                throw new \Exception(__('Error ....'));
            }
            if (!$table1->save($entity1)) {
                throw new \Exception(__('Error ....'));
            }

            $table2 = TableRegistry::get('Table2');
            $entitiy2 = $table2->newEntity();
            $entitiy2->foo = 'bar';

            //validate
            if ($entitiy2->errors()) {
                throw new \Exception(__('Error ....'));
            }
            if (!$table2->save($entitiy2)) {
                throw new \Exception(__('Error...'));
            }
            $conn->commit();
        } catch (\Exception $ex) {
            //error handling...
            $conn->rollback();
        }
    }`

What do you think about? Is there a better approach? I would like to hear your opinion :)

markstory commented 7 years ago

Why not use $connection->transactional()? It does pretty much exactly what you have in your code, but doesn't require a try/catch.

mo86 commented 7 years ago

Thx I didnt know about that. But I still think it would be great to add a more complex saving example with two or more models/tables and the use of the last insert id as a foreign key for the following tables inside a transaction. Maybe we could add a "best practises" category to the documentation where we show how to solve common problems in the "cake way". I mean a collection of example code with a short summary. Just an idea.

markstory commented 7 years ago

I am not sure a best practices section would age well. I have seen them just collect all sorts of information that could fit into the documentation relevant to each sample.

Normally you shouldn't need to use last insert id. The ORM can automatically connect foreign key data together.

saeideng commented 6 years ago

Thx I didnt know about that. But I still think it would be great to add a more complex saving example with two or more models/tables and the use of the last insert id as a foreign key for the following tables inside a transaction.

            $result=$this->Users->connection()->transactional(function() use ($user,$profile){
                    if ($this->Users->save($user)) {
                                    // .....
                                    $profile->user_id = $user->id;
                                    if ($this->Users->Profiles->save($profile)) {
                                               //other logic
                                                return true;
                                    }
                    }
                    return false;
            });
            if($result){
                    $this->Flash->success(__('....'));
                        return $this->redirect(['action' => 'index']);
                } else {
                        $this->Flash->error(__('........'));
            }
saeideng commented 5 years ago

I think book.cakephp.org and API documentation is clear enough