XAMPPはMySQLですが、他に有名なフリーのDBとしてPostgreSQLが存在します。
商用としては高性能なOracleが、Windows用にはMSSQL等があります。
PHPはデフォルトで、それぞれのDBMSに対して専用の接続関数を用意しています。
MySQLならmysql_connect()、PostgreSQLならpg_connect()、Oracleならoci_connect()といったかんじです。
しかしこれではDBが変更になった際など、全てのプログラムからDB関係の関数を全て探し出して変更しなければなりません。
そんなことをすると恐ろしい手間がかかるので、それを避けるためにDataAccessObjectが編み出されました。
まあ簡単に言うとDBにアクセスするクラスを作成し、コンストラクタに'mysql'なり'postgres'なりの文字を与えれば、あとの接続やSQLの実行といった部分は全部クラス内でやってくれますよということです。
これによって、例えばDBが変更になった場合でも、最初の引数だけ変更すればOKとなるわけです。
更にDBのインスタンス化を行う部分を一つのファイルに纏めてしまえば、DBが変更になっても変更箇所はたった一箇所で済むようになります。
まあ実際はそううまくいくわけもなく、ベンダ固有のSQL実装など修正部分が出てくるのは避けられませんが、それでも素のDB接続関数を用いるよりは遙かに簡単になります。
PHPでDataAccessObjectパターンを行う手段は幾つか存在します。
有名どころではPear::MDB2やPear::DB_DataObjectがありますが、PHP5でようやくモジュールとしてPDOが登場しました。
http://jp.php.net/manual/ja/book.pdo.php
Pearと違ってCで書かれているので高速性が期待できます。
早速使ってみましょう。
Linuxではインストールが必要ですが、Windowsではphp.iniのコメントを外すだけです。
http://jp.php.net/manual/ja/pdo.installation.php
まずはDBの準備です。
phpMyAdminから編集するなりSQLを打つなりでテスト用DBとテーブル、ユーザを作成します。
CREATE DATABASE `testdb` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; |
できました。
booksテーブルは別にこんなに立派である必要はありませんが、昔作ったのを流用しました。
とりあえず適当に一件登録しておいてください。
次はPHPの用意です。
pdo.php
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//PDO
define('DB_DSN','mysql:host=localhost;dbname=testdb');
define('DB_USERNAME','testuser');
define('DB_PASSWORD','testpass');
$db = new PDO(DB_DSN,DB_USERNAME,DB_PASSWORD);
$select=$db->query('SELECT * FROM books');
while($loop=$select->fetch(PDO::FETCH_ASSOC)){
$ret[]=$loop;
}
|
簡単に$dbにPDOオブジェクトが作成されました。
後はこれに対しSQLを書いていくだけですが、PDOを経由しているので実行する時にDBの種類を考える必要がありません。
もしDBが変更になった場合、最初のDB_DSNを、
define('DB_DSN','pgsql:host=localhost port=8888 dbname=testdb');
等と変更するだけです。
移植性、独立性の高いコードを書くことが出来ました。
さっそく実行。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
array(11) {
["id"]=>
string(1) "1"
["name"]=>
string(5) "?????"
["author"]=>
string(2) "??"
["publisher"]=>
string(6) "??????"
["price"]=>
string(4) "1050"
["isbn"]=>
string(14) "978-4883810451"
["date"]=>
string(10) "2006-10-01"
["comment"]=>
string(7) "????(?)"
["created_at"]=>
string(19) "2008-08-15 11:45:49"
["updated_at"]=>
NULL
["deleted_at"]=>
NULL
|
お?
見事に文字化けしています。
PHPもUTF8、MySQLもUTF8、ブラウザもUTF8なのに何故?
実はこれMySQLからPHPへの出力時に変な文字コードで出力しているのが原因です。
MySQLからの出力は、テーブルの文字コードそのままではなく、設定ファイルに従って変換された上で出力されます。
このデフォルト値がlatin1なる日本語の使えないコードであるため、日本語が全て文字化けしてしまうのです。
というわけで
$db->query('SET NAMES utf8');
の一文を入れるだけで直るのですが、セキュリティ上の理由から勧められていません。
http://nonn-et-twk.net/twk/why-set-names-in-php-is-bad
かわりにmysql_set_charset()を使えと書いてありますが、PDOでどうしろと。
MySQL側で動作を修正した場合、MySQL全体に影響が及ぶので、他のシステムが存在した場合そちらが動作不具合を起こす可能性もあります。
http://dev.mysql.com/doc/refman/4.1/ja/charset-connection.html
まあ今回はローカルで特に問題ないのでmy.cnfを修正しました。
マニュアルには
default-character-set-name=character_set_name
とか書いてありますが、正しくは
default-character-set = utf8
です。
修正方法は、my.cnf(Windows上では短縮ダイアルに見える)の適当なところに、
[mysqld]
default-character-set = utf8
skip-character-set-client-handshake
という文字を突っ込むだけです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
array(11) {
["id"]=>
string(1) "1"
["name"]=>
string(16) "恋空〈上〉"
["author"]=>
string(7) "美嘉"
["publisher"]=>
string(19) "スターツ出版"
["price"]=>
string(1) "0"
["isbn"]=>
string(15) "978-4883810451"
["date"]=>
string(10) "2006-10-01"
["comment"]=>
string(18) "スイーツ(笑)"
["created_at"]=>
string(19) "2008-01-01 01:01:01"
["updated_at"]=>
NULL
["deleted_at"]=>
NULL
|
めでたし。
トラックバック
コメント
ネットは死ぬわ電話は死ぬわ俺は死ぬわでもう駄目です。
NEの筈だったのに何故か今はWeb開発に居るし。
複数列が返るselect文をPDO::queryすると落ちる
select id from~はOK
一列しかないテーブルにselect * もOK
select id,nameとかすると死
というようなことを言われました。
http://www.tokumaru.org/d/20100701.html
PDOはデフォルトではプレースホルダを使わず勝手にエミュレーションしてしまうらしいので、コンストラクタに引数を渡してやらないといけないようです。
http://d.hatena.ne.jp/do_aki/20100221/1266746673
俺は前の会社をやめて転職して中部に引越したよ。
たまには連絡くれ。
では。