[PHP] データベース処理を楽にするclass

今回は、データベースアクセスを考えてみたいと思います。

ですが、その前に覚えておいて欲しいことがあります。
それは、【私は以下のclassを使っていない】ということです。
その点を理解してお読みください。そして最後に"使わない理由"を記述しています。

PHPがサポートするデータベースはいくつか種類がありますが、

  • mysql_query() : MySql
  • mssql_query() : Microsoft SQL Server
  • pg_query() : Postgre

このように、関数の _(アンダーバー)以前がデータベースを意味し、同じような処理を行う関数は、_(アンダーバー)以降は同じ名前で対応するようになっています。

そこで、以下では、MySqlについて記述していきますが、他のデータベースをお使いの方は、 関数名の mysql_ の箇所を、 mssql_ や pg_ に置き換えて利用して頂ければと思います。
MySql関数一覧 / Microsoft SQL Server関数一覧 / Microsoft Postgre関数一覧

コードを分割して記述しています。実際は1つのファイルに繋げて記述します。

/*
 * データベース(MySql only)
 *
 * 本クラスはMySql専用です。
 * 他のデータベースを利用の方は、各メソッド内を書き換えてください。
 * 多くの場合は、mysql_ の箇所を該当のデータベースのものに置き換える
 * だけで利用できるかと思います。
 *
 * try{}chatch() を行うため、set_error_handler() が必要です。
 */
class Aulta_Database{

  private $Connection;  // データベースコネクション

  /*
   * コンストラクタ
   */
  function __construct(){}

  /*
   * デスクトラクタ
   */
  function __destruct(){}

ここのポイントとして、とりあえずコネクションを保持する変数を宣言します。
コンストラクタ、デスクトラクタでは特に何も行いません。(コメントオフしてもOKです)

/*
   * データベースに接続する
   */
  public function connect($DbHost, $DbUser, $DbPass, $DbName)
  {
    $this->Connection = false;
    $ErrorString = "";
    try{
      // 接続を試みる
      $this->Connection = mysql_connect($DbHost, $DbUser, $DbPass);
      if ($this->Connection === false){
        $ErrorString .= "mysql_connect[A] : "
          . $DbHost . ' : ' . $DbUser;
      } else {
        //  文字コードをUTF-8に。(UTF-8と仮定)
	      if (mysql_query("SET NAMES utf8", $this->Connection)
                === false){
	        $ErrorString .= "SET NAMES utf8";
	      } else {
	        // 使用するデータベースを選択
  	      if (mysql_select_db($DbName, $this->Connection)
                === false){
  	        $ErrorString .= "データベースが見つかりません。:" . $DbName;
	        }
	      }
	    }
    } catch (Exception $E){
      $ErrorString .= "mysql_connect[B] : "
        . $DbHost . ' : ' . $DbUser;
    }
    if (strlen($ErrorString) > 0){
      writeLog(C_LOG_ERROR, __FILE__, __LINE__, $ErrorString);
      return false;
    }
    return true;
  }

データベースに接続するための connect()メソッドを定義します。
引数には、ホスト名、ユーザー名、パスワード、データベース名を指定します。
try{} を使用するため、先にset_error_handler()を行う必要があります。

正常時は true を、エラー時は false を返します。

writeLog() は、オリジナルのログ関数です。ログを残すwriteLog()を参照してください。
または、他のログ関数を利用している方は書き換えてください。

/*
   * mysql_real_escape_string()を実行する
   * 戻り値:正常時 string, エラー時 === false
   */
  public function realEscape($Text)
  {
    return mysql_real_escape_string($Text, $this->Connection);
  }

シングルクォートやダブルクォートなど、SQL文として不適切な文字列をエスケープします。
$Sql = "select * from hoge where fuga =' . $Class->realEscape("ab'cd'e") . '";
などと、SQL文を作成する時に使用します。

/*
   * sqlを実行する
   * 戻り値:正常時 Result, エラー時 === false
   */
  public function runSql($Sql)
  {
    $Result = mysql_query($Sql, $this->Connection);
    if ($Result === false){
      writeLog(C_LOG_ERROR, __FILE__, __LINE__, "sql error : " . $Sql);
    }
    return $Result;
  }

引数のSQLを実行します。
戻り値は、mysql_query()関数の戻り値と同じです。
mysql_query()のリファレンスでご確認ください。

/*
   * 結果セットを開放する
   */
  public function freeResult($Result)
  {
    if (is_resource($Result)) return mysql_free_result($Result);
    return false;
  }

結果セットを開放します。

/*
   * sqlから指定したフィールドの値を配列で取得
   */
  public function getFields($Sql, $FieldNames)
  {
    $ret = false;
    $Result = $this->runSql($Sql);
    if ($row = mysql_fetch_array($Result)){
      $ret = array();

      if (is_array($FieldNames)){
        $Count = count($FieldNames);
        foreach ($FieldNames as &$value){
          $FieldName = $FieldNames[$value];
          $ret[$FieldName] = $row[$FieldName];
        }
      } else {
        $ret[$FieldNames] = $row[$FieldNames];
      }
    }
    $this->freeResult($Result);
    if ($ret === false){
      writeLog(C_LOG_ERROR, __FILE__, __LINE__, "sql error : " . $Sql);
    }
    return $ret;
  }

}  // ※ これで終わりなので、classを閉じる括弧を記述してください。

引数のSqlから、$FieldNamesで指定されたフィールドを連想配列として取得します。
$FieldNamesは、string、もしくは配列でフィールド名を指定します。
例えば、 select count(id) as Count from hoge など、 結果が1レコードであることが確定しているときに使用することを想定しています。

次は、このクラスの使用例を記述します。

$HtmlBody = '';

// Utility.php にAulta_Databaseクラスが記述されている想定
include "./Utility.php";

// データベースクラスをnewする
$Aulta_Database = new Aulta_Database();

// データベースに接続を試みる
$ret = $Aulta_Database->connect("localhost", "root", "", "dbname");

// 正常接続時は$retにtrue、エラー時は$retにfalseが入る
if ($ret === false){
  writeLog(C_LOG_ERROR, __FILE__, __LINE__, "データベース接続エラー");
  echo "データベース 接続エラー<br />"
    . "実際は、ここで500エラーを発行";
  exit;
}
// -------------------------
// SQL文を作成
$Sql = "select CURTIME() as CurrentTime";
// SQLを実行
$Result = $Aulta_Database-&gt;runSql($Sql);
// ここで、目的に応じて$Resultを処理します。
if ($Result === false){
  $HtmlBody .= 'SQL実行エラー';
} else {
  if ($row = mysql_fetch_array($Result)){
    $HtmlBody .= "現在の時間は、" . $row["CurrentTime"];
  }
}
// $Resultを開放
$Aulta_Database-&gt;freeResult($Result);
// -------------------------
// SQL文を作成
$Sql = "select CURTIME() as CurrentTime";
// フィールド名を指定してSQLを実行
$Result = $Aulta_Database-&gt;getFields($Sql, "CurrentTime");
if ($Result !== false){
  $HtmlBody .= "<hr />" . $Result["CurrentTime"];
}
// -------------------------
//  出力
?&gt;

※ 私がこのクラスを使わない理由は、次のエントリに書きます。
次 : [PHP] データベースclassを使わない理由