PHP入門 データベースへの接続
PHPからデータベースに接続する方法を解説しています。
データベース接続
PHPアプリからデータベースを操作するには、まずデータベースに対して接続を確立する必要があります。
<?php
$dsn = 'mysql:dbname=test; host=127.0.0.1; charset=utf8';
$usr = 'root';
$passwd = 'test';
try{
$db = new PDO($dsn, $usr, $passwd);
print '接続に成功しました';
}catch (PDOException $e){
die("接続エラー:{$e->getMessage()}");
}finally {
$db = null;
}
接続と切断
データベースへの接続を管理するのは、PDOクラスの役割です。まず、PDOクラスをインスタンス化します。接続を切断するには、オブジェクト変数$dbにnullをセットします。ただし、データベースへの接続はスクリプトの終了時に自動的に切断されます。
構文:PDOクラス
new PDO(string $dsn [, string $username [, string $passwd [, array $options]]])
$dsn | データベース接続文字列 |
$username | 接続ユーザー名 |
$passwd | 接続時のパスワード |
$options | 接続オプション |
データベース接続文字列は、データベースに接続するための情報(ホスト名やポート番号、データベース名など)を一定の書式でまとめたものです。データベース接続文字列の書式は、接続先のデータベースによって異なります。
データベース接続文字列の書式
接続先のデータベース | 接続文字列 |
---|---|
MySQL/MariaDB | mysql:host=127.0.0.1;port=3307;dbname=testdb |
mysql:unix_socket=/tmp/mysql.sock;dbname=testdb(Unixソケット) | |
PostgreSQL | pgsql:host=127.0.0.1;port=5432;dbname=testdb;user=root;password=test |
SQLite | sqlite:test.sqlite(ファイルシステム上のデータベース) |
sqlite::memory:(メモリ上のデータベース) | |
Oracle | oci:dbname=testdb(tnsnames.ora使用時) |
oci:dbname=//127.0.0.1:1521/testdb(instantclient使用時) | |
SQL Server | mssql:host=127.0.0.1;dbname=testdb |
ODBC | odbc:testdb(ドライバーマネージャー) |
odbc:Driver={Microsoft Access Driver(*.mdb)};Dbq=C:\\testdb.mdb;Uid=Admin |
例外処理の基本(try~catch~finally命令)
データベースへの接続ができなかった場合は、PDOException例外を発生します。例外とは、アプリの実行時に発生する異常な状態のことです。例外処理とは、あらかじめ発生するかもしれないエラーを想定しておき、そのエラーが発生した場合に行うべき処理のことです。例外を表現するにはtry~catch~finally命令を利用します。
構文:try~catch~finally命令
try{
//例外が発生する可能性があるコード
} catch( 発生するかもしれない例外の種類 例外を受け取る変数名 ){
//例外発生時の処理
}finally{
//例外の有無にかかわらず実行されるコード
}
try~catch~finally命令を利用していない場合、データベースへの接続が失敗するとスクリプトが終了してしまいます。tryブロックでコードをくくった場合には、例外が発生しても、処理はそのままcatchブロックに引き継がれ処理が継続します。最後のfinallyブロックは、例外があったかどうかにかかわらず、最終的に必ず実行されるブロックです。tryブロックの中で利用したリソースの後始末などのために利用します。例えば、データベースの切断など記述します。
例外クラスで呼び出せるメソッド
メソッド | 概要 |
---|---|
getMessage() | 例外メッセージ |
getCode() | 例外コード |
getFile() | 例外が発生したファイル名 |
getLine() | 例外発生した行数 |
getPrevious() | 前の例外 |
getTrace() | バックトレース(配列) |
getTraceAsString() | バックトレース(文字列) |
接続スクリプトの外部化
データベースへの接続は定型的で、データベース接続文字列やユーザー名、パスワードのような環境依存の情報が複数個所に分散しているのは、よくないためユーザー定義関数として外部化します。
DbManager.php
<?php
function getDb() :PDO{
$dsn = 'mysql:dbname=testdb; host=127.0.0.1; charset=utf8;';
$usr = 'testusr';
$passwd = 'testpw';
//データベースへの接続を確立
$db = new PDO($dsn, $usr, $passwd);
return $db;
}
定義したgetDb関数を呼び出す方法
<?php
require_once './DbManager.php';
$db = getDb();
接続オプション
データベース接続時の挙動を決めるパラメーター情報のことを接続オプションと言います。接続オプションは、PDOクラスをインスタンス化する場合に連想配列「オプション名 => 設定値」の形式で指定するか、setAttributeメソッドを使って個別に設定できます。
構文:setAttributeメソッド
PDO::setAttribute(int $attribute, mixed $value):bool
$attribute | オプション名 |
$value | 設定値 |
利用可能な接続パラメーター
定数 | 概要 | 設定値/戻り値 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
PDO::ATTR_AUTOCOMMIT | 自動コミットを有効化するか(true/false) | true | ||||||||
PDO::ATTR_TIMEOUT | データベースとの通信におけるタイムアウト時間 | – | ||||||||
PDO::ATTR_CASE | 取得したフィールド名の変換方法 | PDO::CASE_NATURAL | ||||||||
| ||||||||||
PDO::ATTR_ERRMODE | エラーの通知方法 | PDO::ERRMODE_EXCEPTION | ||||||||
| ||||||||||
PDO::ATTR_ORACLE_NULLS | 空文字列⇔null値を変換するか(Oracleだけでなく、全ドライバーで利用可) | PDO::NULL_NATURAL | ||||||||
| ||||||||||
PDO::ATTR_PRERSISTENT | 接続的接続を有効にするか(true/false) | false | ||||||||
PDO::ATTR_DRIVER_NAME | ドライバー名 | mysql | ||||||||
PDO::ATTR_CONNECTION_STATUS | サーバーへの接続状態 | 127.0.0.1 via TCP/IP | ||||||||
PDO::ATTR_SERVER_INFO | サーバー状態 | Uptime:2293 Threads:7 Questions:6 Slow Queries:0 Opens: 16 Flush tables:1 Open tables: 10 Queries per second avg:0.002 | ||||||||
PDO::ATTR_SERVER_VERSION | サーバーのバージョン | 5.5.5-10.4.17-MariaDB | ||||||||
PDO::ATTR_CLIENT_VERSION | クライアントのバージョン | mysqlnd 8.0.0 |
1、PDO::ATTR_ERRMODE
接続中にエラーが発生した場合、これをどのように通知するか決めます。PDO::ATTR_ERRMODEパラメーターにPDO::ERRMODE_SILENTを指定した場合、PHPはエラーが発生した場合にもエラーコードを設定するだけでエラー出力しません。もし、この設定で発生したエラー確認したい場合には、PDO::errorCode、errorInfoメソッドを使用してください。errorInfoメソッドは、次に示すエラー情報を配列として返します。
errorInfメソッドに含まれるエラー情報
インデックス | 概要 |
---|---|
0 | 共通のエラーコード |
1 | ドライバー固有のエラーコード |
2 | ドライバー固有のエラーメッセージ |
errorInfoメソッドに含まれる共通エラーコードは、errorCodeメソッドによって返される値と等価です。
<?php
require_once './DbManager.php';
$db = getDb();
$db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db->exec('MECHA KUCHA');
if($db->errorCode() !== '00000'){ //➊
$info = $db->errorInfo();
print "エラーコード:{$info[0]}<br />";
print "エラー(ドライバー):{$info[1]}<br />";
print "エラーメッセージ:{$info[2]}<br />";
}
execメソッドは、データベースに対して問い合わせ(クエリ)命令を発行するためのメソッドです。SQL命令に対する値のバインド(代入)が不要で、かつ、結果を必要としないクエリを発行する場合には、execメソッドを利用します。
構文:execメソッド
PDO::exec(string $statement): int
$statement | 任意のクエリ |
PDO::ATTR_ERRMODEの既定値は、PHP7まではPDO::ERRMODE_SILENT、PHP8以降はPDO::ERRMODE_EXCEPTIONです。バージョンにかかわらず、クエリによって発生したエラーをtry~catch命令で処理するためには、明示的にPDO::ERRMODE_EXCEPTIONを設定します。
DbManager.php
<?php
function getDb() :PDO{
$dsn = 'mysql:dbname=testdb; host=127.0.0.1; charset=utf8;';
$usr = 'testusr';
$passwd = 'testpw';
//データベースへの接続を確立
$db = new PDO($dsn, $usr, $passwd);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
}
これによって、クエリ実行のつど(❶)のコードを記述する必要がなくなります。
<?php
require_once './DbManager.php';
try{
$db = getDb();
$db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db->exec('MECHA KUCHA');
} catch(PD){
if($db->errorCode() !== '00000'){
print "エラーコード:{$info[0]}<br />";
print "エラーメッセージ:{$info[2]}<br />";
}
2、PDO::ATTR_CASE
データベースサーバーによって、取得したテーブルのフィールド名をそのまま返さず、自動的に大文字(小文字)に変換するものがあります。そのような場合、PDO::ATTR_CASEパラメーターを設定しておくことで、こうしたデータベースごとの違いを吸収できます。
<?php
require_once './DbManager.php';
$db = getDb();
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
print_r($db->query('SELECT * FROM book') -> fetchAll(PDO::FETCH_ASSOC));
//結果:Array([0]=>Array([ISBN]=> ・・・・・[TITLE] => ・・・・))
PDO::ATTR_CASEパラメーターをPDO::CASE_UPPER(大文字に変換)としているので、フィールド名がすべて大文字で得られることが確認できます。
3、PDO::ATTR_PERSISTENT
PDO::ATTR_PERSISTENTパラメーターを有効にすると、持続的接続が有効になります。持続的接続とは、スクリプトが終了しても破棄せずに維持され、他から要求があった場合にこれを再利用する接続のことを言います。持続的接続によって、接続確率のためのオーバーヘッドを軽減できるので、特にアクセス数が多いサイトではパフォーマンス改善になります。
$db = new PDO($dsn, $usr, $passwd, [PDO::ATTR_PERSISTENT => true]);