思い立ったら何かを書いて行くブログ@DreamProject中の人

DreamProjectというゲーム制作サークルで奮闘しているかも知れない人の徒然なるブログ

【PHP/MySQL】PDOで複数のテーブルを動的に取得してSQL文を結合する方法

 

 

先日悩んでとりあえず解決した件のアウトプットを健忘録として書いておきます。

 

動的にテーブル一覧を取得して一行のSQL文に結合するPHPコード

<?php
// データベースに接続するために必要なデータソースを変数に格納
  // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
$dsn = 'mysql:host=ホスト名;dbname=データベース名;charset=utf8';
 
  // データベースのユーザー名
$user = 'ユーザー名';
 
  // データベースのパスワード
$password = 'パスワード';
 
// tryにPDOの処理を記述
try {
 
  // PDOインスタンスを生成
  $dbh = new PDO($dsn, $user, $password);
 
// エラー(例外)が発生した時の処理を記述
} catch (PDOException $e) {
 
  // エラーメッセージを表示させる
  echo 'データベースに接続できません' . $e->getMessage();
 
  // 強制終了
  exit;
 
}

// テーブル一覧取得
$table_stmt = $dbh->prepare(implode(" ", array(
    "SELECT table_name",
    "FROM INFORMATION_SCHEMA.TABLES",
    "WHERE " . implode(" AND ", array(
        "table_name LIKE :table_name ESCAPE '!'",
        "table_schema = :table_schema",
    )),
)));
$table_name = '%' . preg_replace( '/(?=[!_%])/' , '!', '検索するテーブル名') . '%';
$table_schema = 'データベース名';
$table_stmt->execute(compact('table_name', 'table_schema'));
$table_list = $table_stmt->fetchAll(PDO::FETCH_COLUMN);

(中略)

// 取得テーブル名を元にテーブル結合SQLに変換
$no = 0;
$last = count($table_list) - 1;

if (!empty($table_list)) {

  foreach ((array)$table_list as $table_name) {
    switch ($no++) {
      case $no:
        $sql = 'SELECT * FROM '.$table_name.' UNION ALL';
        break;
      case $last;
        $selects = preg_replace('/^/', 'SELECT * FROM ', $table_list);
        $sql = implode(' UNION ALL ', $selects) . ' ORDER BY id';
        break;
    }
  }
}

// テーブル名をクォートで囲む処理

$sql = preg_replace('/検索するテーブル名/', '`置換するデーブル名', $sql);
$sql = preg_replace('/\sUNION\sALL/', '` UNION ALL', $sql);
$sql = preg_replace('/\sORDER\sBY/', '` ORDER BY', $sql);

// SQL文実行
$stmt = $dbh->query($sql);

(以下略)

?>

 

これを導き出すためにかなりの時間悩んで、結局色んなところにテーブル名自動取得部分を質問させてもらったので、一応完成形の部分を還元できればという感じです。

使われるかどうかは置いといて、こういった情報が少なかったので、こんな風にする方法がありますよという感じで見てもらえばと思いますけどめんどいですね。

 

フォームの項目追加でテーブルが増えて行くような仕様のプラグインに出会って、どうしてもテーブルを結合して表示しないといけないような場合とかに使えるんじゃないかと・・・。

SQL文の内部結合とか外部結合で結合する場合はもっと別のやり方を考えないといけませんが、UNION句で簡単に結合するならこれでイケると思います。

 

あと調べて思ったのが未だにPHP5.3以降で非推奨となった mysql_***() 系の関数使われている方意外と多かったです。私はPDOが楽なのでPDO使っていますが、今はPDOとかの方が安全なのでそちらを使われた方が良いです。と言っても簡単に修正できない場合もありますので mysql_***() 系の関数使われている方は移行時に注意して下さいね。

(既にPHP7とか使う人が出て来ているのでそちらだと確実にerror吐きます)

 

今回のまとめ

●項目追加毎に動的にテーブルが増えて行く仕様のプラグイン改修はなるべく避ける

mysql_***()系の関数はPHP5.3以降は非推奨なので使わないように

 

以上、PHPやる人の助けになればいいですね(*´ω`*)