メソッドを呼ぶごとに別のsqliteファイルにコネクションする方法

こんな使い方をするケースも稀だと思いますが、要件だったのでメモ。

  1. SQLiteファイルは外部システムから動的に追加されていく
  2. 接続したいSQLiteファイルは画面によって変わる
  3. 同時に接続したいSQLiteファイルは1個とは限らない

動的に増えていくファイルをすべてキャッチしているとキリがないのでapp.phpのDatasourcesに定義する方法は不採用。

フレームワーク内の実装ではあるが、データソースもConnectionManagerも使わず、PDOをインポートして共通メソッドに接続ファイルパスを引数で渡してコネクションを作る方法を採用。

1. ベースクラスでコネクション取得用のメソッドを定義


class AppBaseController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }

    /**
     * SQLiteのコネクション取得
     *
     * @param string $dbname
     * @return PDO $pdo
     */
    public function getConnectionSQLite($dbname)
    {
        try {
            $pdo = new PDO(
                'sqlite:' . ROOT . '/database/' . $dbname . '.sqlite',
                'my_app',
                'secret',
                array(
                    PDO::ATTR_PERSISTENT => true,
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                )
            );
        } catch (PDOException $e) {
            header('Content-Type: text/plain; charset=UTF-8', true, 500);
            exit($e->getMessage());
        }
        return $pdo;
    }
}

2. 特定のDBとコネクションしたい各Controller側で処理を呼び出す


<?php
use PDO;

class ChildController extends <?php
use PDO;

class ChildController extends AppBaseController
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }

    public function index()
    {
        $pdo1 = $this->getConnectionSQLite('sqliteFileA');
        $stmt = $pdo1->query('SELECT * FROM tebleA');
        $data1 = $stmt->fetch(PDO::FETCH_ASSOC);

        $pdo2 = $this->getConnectionSQLite('sqliteFileB');
        $stmt = $pdo2->query('SELECT * FROM tebleB');
        $data2 = $stmt->fetch(PDO::FETCH_ASSOC);

        $result = array_merge(array_merge($data1, $data2));

        $this->set([
            'result' => $result,
            '_serialize' => ['result']
        ]);
    }
}

コメントを残す