Correctly Using Transactions
Using database transactions in webman is the same as in other frameworks. Here are some points to pay attention to.
Code Structure
The code structure is the same as in other frameworks, for example, the usage in Laravel (similar to think-orm).
Db::beginTransaction();
try {
// ..Business processing omitted...
Db::commit();
} catch (\Throwable $exception) {
Db::rollBack();
}
It is especially important to note that you must use \Throwable
and cannot use \Exception
, because during business processing, an Error
might be triggered, which does not belong to Exception
.
Database Connection
When operating models in a transaction, it is particularly important to pay attention to whether the model is set up with a connection. If the model has a specified connection, it must be indicated when starting a transaction; otherwise, the transaction will be invalid (similar to think-orm). For example:
<?php
namespace app\model;
use support\Model;
class User extends Model
{
// The connection is specified for the model here
protected $connection = 'mysql';
protected $table = 'users';
protected $primaryKey = 'id';
}
When the model has a specified connection, starting a transaction, committing a transaction, and rolling back a transaction must specify the connection.
Db::connection('mysql')->beginTransaction();
try {
// Business processing
$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 the business code causes a request not to commit its transaction. To quickly locate which controller method did not commit the transaction, you can install the webman/log
component. This component will automatically check for uncommitted transactions after the request is completed and log it, with the log keyword being Uncommitted transactions
.
Installation method for webman/log:
composer require webman/log
Note
After installation, you need to restart; reload will not take effect.