#概要
データベースを操作するクラスをテーブルごとに分ける設計を考えたが、復数のテーブル操作を一つのトランザクションで行う際に設計上つまづいたのでメモメモ
#課題
クラスを下記のような構成で作成したが、一つのテーブルを操作するたびにDBへの接続を行う仕様になっていたため、一つのトランザクションで復数テーブルの操作ができなくなってしまいましたorz
- Database
内容:コンストラクタでDBへの接続を行う。テーブル毎のクラスで共通して使用するメソッドを定義 - Table1 extends Database
内容:テーブル1を操作するメソッドを定義 - Table2 extends Database
内容:テーブル2を操作するメソッドを定義
ソースはこんな感じ
class Database
{
const SERVER = "サーバー名";
const USER = "ユーザ名";
const PASS = "パスワード";
const DATABASE = "DB名";
public $link;
public function __construct(){
$this->link = new mysqli(self::SERVER,self::USER,self::PASS,self::DATABASE);
if($this->link->connect_errno){
die("接続失敗".$this->link->error);
}
}
}
class Table1 extends Database {
public function add(){
$link->query("INSERT INTO table1 (・・・・) VALUES(・・・・)");
}
}
class Table2 extends Database {
public function add(){
$link->query("INSERT INTO table2 (・・・・) VALUES(・・・・)");
}
}
//それぞれでデータベースに接続しているためどうやって一つのトランザクションで復数テーブルを操作しよう。。。
$table1 = new Table1();
$table1->add();
$table2 = new Table2();
$table2->add();
#解決方法
理想の流れは
DB接続 → トランザクション開始 → テーブル1操作 → テーブル2操作 → コミット
なので、
クラスDatabaseのコンストラクタでDBへの接続を行うことをやめ、DB接続をクラスDatabaseで独立させる。
そして、MySQL サーバーへの接続を表すオブジェクトをテーブル操作するメソッドに引数として渡すことで解決できました。
以下、解決後のソースの流れはこんな感じ
class Database
{
const SERVER = "サーバー名";
const USER = "ユーザ名";
const PASS = "パスワード";
const DATABASE = "DB名";
public $link;
public function connect(){
$this->link = new mysqli(self::SERVER,self::USER,self::PASS,self::DATABASE);
if($this->link->connect_errno){
die("接続失敗".$this->link->error);
}
return $this->link;
}
public function begin_transaction($link) {
return $link->begin_transaction;
}
public function commit($link) {
return $link->commit;
}
}
class Table1 {
public function add($link){
$link->query("INSERT INTO table1 (・・・・) VALUES(・・・・)");
}
}
class Table2 {
public function add($link){
$link->query("INSERT INTO table2 (・・・・) VALUES(・・・・)");
}
}
$DB = new Database();
$link = $DB->connect();
$DB->begin_transaction($link);
$table1 = new Table1();
$table1->add($link);
$table2 = new Table2();
$table2->add($link);
$DB->commit($link);