6


0

PHP PDOオブジェクトは、MySQLトランザクションにすでにある場合、どのように判断できますか?

2つの複雑なPHPオブジェクトがあり、それぞれがいくつかのMySQLテーブルにデータを持っています。

データベースから1つのオブジェクトAを削除するだけで、3つのSQLステートメントが必要になる場合があります。

時々、データベースから1つのオブジェクトBを削除する必要があります。これには4つのSQLステートメントが必要であり、そのオブジェクトBが所有するすべてのオブジェクトAを見つけて削除する必要があります。

したがって、関数delete_A()内で、トランザクション内でこれらのステートメントを実行します。 delete_B()という関数の内部で、delete_A()内のアクティビティをカバーする大きなトランザクションを実行したいと思います。 Bを削除するアトム全体が失敗した場合、そのAをすべてロールバックで復元する必要があります。

delete_A()の定義を更新して、新しいトランザクションを開くようにするにはどうすればよいですか*実行中の大きなトランザクションがまだない場合。

私はこのようなことをできると思っていましたが、 autocommit`属性は beginTransaction() `によって変更されないようです。

function delete_A($a){
  global $pdo;
  $already_in_transaction = !$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
  if(!$already_in_transaction){
    $pdo->beginTransaction();
  }

  //Delete the A

  if(!$already_in_transaction){
    $pdo->commit();
  }
}
function delete_B($b){
  global $pdo;
  $pdo->beginTransaction();
  foreach($list_of_As as $a){
    delete_A($a);
  }
  $pdo->commit();
}

3 Answer


7


`PDO

ATTR_AUTOCOMMIT`はインジケーター属性ではなく、コントロール属性です。 SQLステートメントの終了時に暗黙的にコミットするかどうかを制御します。

進行中のトランザクションがない場合は「0」を返し、コミットまたはロールバックする必要がある未処理のトランザクションがある場合は「1」を返す「PDO

inTransaction()」を呼び出すことができます。 ただし、この関数は文書化されていないため、将来のすべてのバージョンのPDOに存在することに依存しても安全かどうかを判断するのは困難です。

PHP開発者は、関数またはクラスのスコープ内でトランザクションを管理しようとしないことをお勧めします。 アプリケーションのトップレベルでトランザクションを管理する必要があります。

また見なさい:


2


最終的には、 `→ beginTransaction()`によってスローされた例外を使用して、トランザクション中かどうかを判断し、それを使用して内部ループでコミットするかどうかを決定しました。 したがって、 `delete_A()`は次のようになりました。

function delete_A($a){
  global $pdo;
  try {
    $pdo->beginTransaction();
  } catch (PDOException $e) {
    $already_in_transaction = true;
  }

  //Delete the A

  if(!$already_in_transaction){
    $pdo->commit();
  }
}

そして、 `delete_B()`は修正なしで動作します。


1


1つの方法は、 `$ hasTransaction`変数を持つ独自のPDOConnectクラスを作成することです。 次に、それを確認します。 php.netのbeginTransaction関数のコメントに例があります。http://www.php.net/manual/en/pdo.begintransaction.php#81022

それが私の好みです。 その例は微調整やドレスアップなどを必要としますが、最初から良い基礎になるはずです。

*注意事項*トランザクションが機能するには、テーブルがINNODBであることを忘れないでください。 また、トランザクションを機能させるにはINNODBにいる必要があるため、prodigitalsonのアドバイスを受けて、外部キー制約を使用する必要があります。