Nucleus(JP)フォーラム

NucleusCMS日本語版ユーザーのためのサポートフォーラムです。疑問が生じたらまずは記事検索をご利用ください。

ログインしていません。

#1 2012-05-04 18:45:50

Reine
Administrator
From: 大阪
登録日: 2006-06-27
投稿: 80

Re: データベースハンドラー変更に伴うプラグイン書き換えガイド

トピック [4.0の開発 - 19] データベースハンドラーの再設計 で周知されたように、
Nucleus4.0からコアスクリプトが利用するデータベースハンドラーとして
DBクラスが設けられました。
イメージとしては以下のようになります。
DBクラスイメージ
ここでは、各プラグインにおいてsql_xxx()関数からDBクラスを使った
方法へと書き換えを行うためのガイドを掲載します。
不明な点やアドバイス等必要であればコメントをお寄せください。

利用準備編

データベースへの接続・切断
これまで通り、NucleusのコアスクリプトでDBへの接続を完了しているので、プラグイン作者が意識することはありません。
ただし、DBクラスでは単一のDBコネクションしか維持しないため、一時的に別のDBへの接続を必要とする場合は別の接続手法を取るか、下記メソッドを呼び出してください。

DB::setConnectionInfo($handler, $host, $user, $password, $database);

この場合、別のDB接続中にNucleusのDBへアクセスが発生しないように
細心の注意を払う必要があります。

コネクションの切断にはsql_close()の代わりにDB::disConnect()を用います。
ただし、DBクラスはアンロード時に保持しているコネクションを自動的に切断するため、意識して呼び出す必要はありません。

データ取得、更新後は以下のコードで元のNucleusデータベースへの接続に戻すことを忘れないようにしてください。

global $MYSQL_HANDLER, $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE;
DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE);

データベースの選択
sql_real_escape_string($db)の動作に該当するDBクラスメソッドはありません。
DB::setConnectionInfo()をデータベース名まで指定して呼び直す事で、
指定されたデータベースが選択された状態のコネクションを得られます。

文字セットの指定
sql_set_charset($charset)で指定していた文字セットは現在は決め打ちで'utf8'となっていて、DBクラス側で変更手段は設けられていません。


クエリ生成編

エスケープ処理
クエリに渡す文字列のエスケープ処理は

sql_real_escape_string($value)
や、
sql_quote_string($value)

の代わりに

DB::quoteValue($value)

を使用します。
注意点として、sql_real_escape_string()はエスケープ処理のみを行いますが、その処理に該当するDBクラスのメソッドは存在しません。
書き換えた際にはクエリからシングルクォートを削除するのを忘れないようにしてください。
例1

修正前)$query = sprintf('SELECT * FROM A WHERE col1=\'%s\'', sql_real_escape_string($val));
修正後)$query = sprintf('SELECT * FROM A WHERE col1=%s', DB::quoteValue($val));

例2

修正前)$query = "SELECT * FROM A WHERE col1='" . sql_real_escape_string($val) . "'";
修正後)$query = 'SELECT * FROM A WHERE col1=' . DB::quoteValue($val);

日時型形式変換
データベースエンジンによってクエリ上での日時形式の表現に違いがある場合を想定し、その差異をDBクラスで吸収できるようにPHPで用いるUnix タイムスタンプをデータベースで扱える日時形式に変換するためのメソッドを用意してあります。
このメソッドでの返り値の日付文字列はクォートされることに注意してください。

修正前)$query .= "WHERE idate='" . date('Y-m-d H:i:s', $time) . "'";
修正後)$query .= 'WHERE idate=' . DB::formatDateTime($time, $offset);
クエリ実行編

クエリの実行
これまではどのようなクエリでも基本的に次の関数で実行されていました。

sql_query($query)

DBクラスでは用途によって幾つかのメソッドを使い分けることができます。

DB::getValue($statement)

globalfunctions.phpのquickQuery($query)関数の代替メソッドでもあります。
quickQueryとの違いは'result'カラムを決め打ちで返すか、結果セットの1行1カラム目の値を決め打ちで返すかです。

DB::getRow($statement)

これは得られる結果が1行分だけでよい場合に使用します。
結果の1行目を配列として返します。ここでの配列は、カラム名と0で始まるカラム番号で添字を付けた配列となります。

DB::getResult($statement)

結果セットを含むPDOStatement(もしくはPDOStatementに似た)インスタンスを返します。
結果セットの扱いについては後述します。

DB::execute($statement)

INSERT、UPDATE、DELETEなどの更新系クエリを実行するための関数です。
返り値として影響を及ぼした行数を返します。

直前のクエリで挿入したid値の取得
sql_insert_id($connection)の代わりにDB::getInsertId()を使います。

直前のクエリで発生したエラーの取得
sql_error()の代わりにDB::getError()を使います。
ただし、出力形式がPDOでの出力に合わせているため、エラーメッセージを取得する場合は

$err = DB::getError();
echo $err[2];

として、配列の3番目の値を取り出す必要があります。

結果セットの利用
DB::getResult($statement)の返り値に、結果セットとしてPDOStatement
(もしくは同等のインターフェイスを持つMysqlPDOStatement)インスタンスを得ることができます。
sql_xxx()のうち、resultリソースを使う関数に該当する処理の多くはこのPDOStatementインスタンスに対して行います。
呼び出せるメソッドについては以下のPDOStatement クラスのマニュアルを参照してください。
PDOStatement クラス
注意点として、mysql関数をラップしたMysqlPDOStatementクラスは現時点ではプリペアドステートメントに対応していません。
単に結果セットを得るためだけの機能を持っています。

結果セットに対するループ処理
これまでよく目にしていた下記のwhileループは

$res = sql_query($query);
while ( $row = sql_fetch_assoc($res) ) {
	echo $row['col1'];
}

以下のように書き換えることができます。

$res = DB::getResult($statement)
while ( $row = $res->fetch() ) {
	echo $row['col1'];
}
もしくは、イテレータである特性を生かして以下のように記述できます。
$res = DB::getResult($statement)
foreach ( $res as $row ) {
	echo $row['col1'];
}

foreach時の$rowはデフォルトでカラム名と0で始まるカラム番号で添字を付けた配列を返します。


その他

クエリ実行回数の取得
グローバル変数の$SQLCountでカウントされていたレスポンス中におけるクエリ実行回数はDB::getExecCount()で取得できます。
DB::getValue()DB::getRow()DB::getResult()DB::execute()の呼び出し回数をカウントしています。


sql_xxx()関数群について

Nucleus4.0への乗り換えが進んでいく間、プラグインは3.64と4.0双方で動作することが求められると思います。
そのため一時的な互換性確保の処置としてDBクラスメソッドをラップしたsql_xxx()関数を用意しています。
もし、mysql_xxx()関数を使っているのであれば、まずはsql_に書き換えて頂ければと思います。

sql_xxx()関数の利用に当たって注意が2つあります

  • すべてのsql_xxx()関数に対応できているわけではありません。
    nucleus/libs/sql/sql.phpにsql_xxx()関数が定義されているので、対応可否について確認しながら書き換えを行なってください。
    また、このファイルのコードはsql_xxx()関数からDBクラスへの書き換えを行う際に参考になると思います。

  • sql_query()が返す値はリソースではなくPDOStatementインスタンスです。
    もし、sql_query()の返り値に対してis_resource()で判定を行なっている場合は結果がFALSEとなり
    意図しない処理結果となるので合わせて修正を行うようにしてください。


Attachments:
png dbhandler_rework.png, Size: 35.82 KiB, Downloads: 2,136

オフライン

Board footer