Hi everyone,

Today I faced something that I don't know it's a bug or it's a feature when using transactions

For simplicity, I have a Product model, and in one transaction, I delete some row in "product" table, and then immediately save some new row into that table, like this

$transaction = $manager->get();

$oldProducts = Product::find("type = 'old'");
foreach ($oldProducts as $oldProduct) {
        $oldProduct->setTransaction($transaction);
        if (!$oldProduct->delete()) {
            foreach ($oldProduct->getMessages() as $message) {
                $transaction->rollback($message->getMessage());
            }
         }
 }

// $data_arr is an array contain some ids and types
foreach ($data_arr as $data) {
    $newProduct = new Product();
    $newProduct->setTransaction($transaction);
    $newProduct->id = $data->id;
    $newProduct->type = $data->type;

    if (!$newProduct->save()) {
        foreach ($newProduct->getMessages() as $message) {
                $transaction->rollback($message->getMessage());
            }
        }
}

//Everything goes fine, let's commit the transaction
$transaction->commit();

After the script run, there are 2 cases:

  1. If there are some product with type = "old", they will be deleted and no new product is added
  2. If there is no product with type = "old", new products will be added

What I expected is in both case is every product with type = "old" are deleted, and new products are added. If there is something wrong, the rollback must work with both delete and save functions.

What's wrong with my implementation?

Thank you very much