Proper Use of Database Transactions

Using database transactions in webman is the same as in other frameworks. Here are the key points to note.

Code Structure

The code structure is the same as in other frameworks (e.g., Laravel usage, think-orm is similar):

Db::beginTransaction();
try {
    // ..business logic omitted...

    Db::commit();
} catch (\Throwable $exception) {
    Db::rollBack();
}

Important: You must use \Throwable and must not use \Exception, because business logic may trigger Error, which does not extend Exception.

Database Connection

When operating on models within a transaction, pay special attention to whether the model has a connection configured. If the model specifies a connection, you must specify that connection when starting the transaction; otherwise the transaction will not work (think-orm is similar). For example:

<?php

namespace app\model;
use support\Model;

class User extends Model
{

    // Connection specified for the model
    protected $connection = 'mysql';

    protected $table = 'users';

    protected $primaryKey = 'id';

}

When the model specifies a connection, you must specify the connection for begin, commit, and rollback:

Db::connection('mysql')->beginTransaction();
try {
    // Business logic
    $user = new User;
    $user->name = 'webman';
    $user->save();
    Db::connection('mysql')->commit();
} catch (\Throwable $exception) {
    Db::connection('mysql')->rollBack();
}

Finding Requests with Uncommitted Transactions

Sometimes a bug in business code causes a transaction to remain uncommitted. To quickly locate which controller method has an uncommitted transaction, you can install the webman/log component. After each request completes, it automatically checks for uncommitted transactions and logs them. The log keyword is Uncommitted transactions.

Installing webman/log

composer require webman/log

Note
You must restart after installation; reload will not take effect.