トランザクションと複数データソース
単一の DAO
$userDAO->startTransaction();
try {
$userDAO->insert($user);
$userDAO->commit();
} catch (Throwable $e) {
$userDAO->rollback();
throw $e;
}
複数の DAO にまたがるトランザクション
DataSourceManager でグローバルトランザクションを開始すると、それ以降に使用されるすべてのデータソースが自動的にそのトランザクションに参加します。
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;
}
コミットとロールバックは、接続が登録された順序の逆順で実行されます。
DAO へのデータソースの割り当て
DATA_SOURCE_ID 定数をオーバーライドします。
class StatsDAO extends BaseMySqlDAO {
const DATA_SOURCE_ID = 'analytics'; // _Global::$DATA_SOURCES['analytics']
protected string $tableName = 'daily_stats';
}
接続の失敗
データソースに接続できない場合、DAO のコンストラクタは _Flexagon\DB\ConnectionException をスローします(デフォルトの _Global::$DB_CONNECT_FAILURE_FATAL = true の場合)。捕捉しなければ、リクエストは 500 で終了し、コマンドラインでは終了コード 255 になります。レスポンスを自分で決めたい場合は、この例外を捕捉してください。
// 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;
});
メッセージにはデータソース名($e->getDataSourceId()、つまり _Global::$DATA_SOURCES のキー)だけが含まれます。ホストやアカウントを含むドライバーのメッセージはエラーログに出力され、元の PDOException は getPrevious() で取得できます。本番環境では display_errors を無効にしておいてください。捕捉されなかった例外が画面に表示されると、前の例外の内容も含まれてしまいます。
例外をスローする代わりに connect() が false を返すようにするには、$DB_CONNECT_FAILURE_FATAL = false を設定します。