Transactions and Multiple Data Sources
Single DAO
$userDAO->startTransaction();
try {
$userDAO->insert($user);
$userDAO->commit();
} catch (Throwable $e) {
$userDAO->rollback();
throw $e;
}
Transactions Across Multiple DAOs
Start a global transaction with DataSourceManager, and every data source used afterward automatically participates in the transaction.
use _Flexagon\Libs\DataSourceManager;
DataSourceManager::startTransaction();
try {
$userDAO->insert($user);
$orderDAO->insert($order);
$pointDAO->update($point);
DataSourceManager::commit();
} catch (Throwable $e) {
DataSourceManager::rollback();
throw $e;
}
Commits and rollbacks are performed in the reverse order in which connections were registered.
Assigning a Data Source to a DAO
Override the DATA_SOURCE_ID constant.
class StatsDAO extends BaseMySqlDAO {
const DATA_SOURCE_ID = 'analytics'; // _Global::$DATA_SOURCES['analytics']
protected string $tableName = 'daily_stats';
}
Connection Failures
When a data source cannot be reached, the DAO constructor throws _Flexagon\DB\ConnectionException (with the default _Global::$DB_CONNECT_FAILURE_FATAL = true). Left uncaught, the request ends with a 500, or exit code 255 on the command line. Catch it to choose the response yourself.
// public/_entry.php
set_exception_handler(function (Throwable $e) {
if ( $e instanceof \_Flexagon\DB\ConnectionException ) {
http_response_code(503);
TemplateLoader::show('maintenance');
return;
}
throw $e;
});
The message names only the data source ($e->getDataSourceId(), the key in _Global::$DATA_SOURCES). The driver message, which includes host and account, goes to the error log; the original PDOException is available from getPrevious(). Keep display_errors off in production: an uncaught exception printed on screen includes the previous exception too.
Set $DB_CONNECT_FAILURE_FATAL = false to have connect() return false instead of throwing.