📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の11版が非表示) | |||
| 133行目: | 133行目: | ||
== データベースの接続 == | == データベースの接続 == | ||
==== 接続文字列 ==== | |||
PDOクラスのインスタンスを作成することにより、接続が確立される。<br> | PDOクラスのインスタンスを作成することにより、接続が確立される。<br> | ||
コンストラクタには、データソース(DSN)、ユーザ名、パスワードを指定する。<br> | コンストラクタには、データソース(DSN)、ユーザ名、パスワードを指定する。<br> | ||
| 156行目: | 157行目: | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
$<PDOクラスのインスタンス名> = new PDO(<データソース名>, <データベースユーザ名>, <パスワード>, <ドライバオプション>); | $<PDOクラスのインスタンス名> = new PDO(<データソース名>, <データベースユーザ名>, <パスワード>, <ドライバオプション>); | ||
PDO PDO::__construct ( string dsn | |||
[, string username | |||
[, string password | |||
[, array driver_options]]] ) | |||
指定されたデータベースへの接続を表すPDOインスタンスを生成します。 | |||
引数: | |||
dsn | |||
データソース名(Data Source Name)またはDSN。データベースに接続するために必要な情報が含まれる。 | |||
username | |||
DSN文字列のユーザ名。このパラメータは、いくつかのPDOドライバではオプションである。 | |||
password | |||
パスワード。 | |||
DSN文字列で必要とされる場合に指定。 | |||
driver_options | |||
ドライバ固有の接続オプションを指定するキー=> 値の配列 | |||
戻り値: | |||
成功時にPDOオブジェクトを返す。 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
| 196行目: | 221行目: | ||
*: 値は予め用意されている定数以外に、論理値や文字列等の一般的な値でもよい。 | *: 値は予め用意されている定数以外に、論理値や文字列等の一般的な値でもよい。 | ||
<br> | <br> | ||
==== ドライバオプション ==== | |||
ドライバオプションとその値を以下に示す。<br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// ドライバオプションの使用例 | |||
$options = [ | |||
// エラー発生時に例外をスロー | |||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, | |||
// フェッチモードをデフォルトで連想配列に設定 | |||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, | |||
// プリペアドステートメントを有効化 | |||
PDO::ATTR_EMULATE_PREPARES => false, | |||
// 持続的な接続を無効化 | |||
PDO::ATTR_PERSISTENT => false, | |||
// カラム名を小文字に変換 | |||
PDO::ATTR_CASE => PDO::CASE_LOWER | |||
]; | |||
$db = new PDO( | |||
'mysql:host=localhost;dbname=sampledb;charset=utf8mb4', | |||
'root', | |||
'root', | |||
$options | |||
); | |||
</syntaxhighlight> | |||
<br> | |||
* PDO::ATTR_ERRMODE | * PDO::ATTR_ERRMODE | ||
*: | *: エラーレポートの方法を設定するための属性である。 | ||
*: クエリの実行でエラーが起きた場合、どのように処理をするかを指定する。 | |||
*: 初期値は、<code>PDO::ERRMODE_SILENT</code>である。 | *: 初期値は、<code>PDO::ERRMODE_SILENT</code>である。 | ||
** PDO::ERRMODE_EXCEPTION | ** PDO::ERRMODE_EXCEPTION | ||
**: | **: エラーが発生した時に例外 (PDOException例外クラス) をスローする。 | ||
**: エラーを例外としてキャッチできるようになり、デバッグが容易になる。 | |||
** PDO::ERRMODE_WARNING | ** PDO::ERRMODE_WARNING | ||
**: クエリの実行Lで発生したエラーをPHPのWarningとして報告する。 | **: クエリの実行Lで発生したエラーをPHPのWarningとして報告する。 | ||
| 210行目: | 267行目: | ||
*: <br> | *: <br> | ||
* PDO::ATTR_DEFAULT_FETCH_MODE | * PDO::ATTR_DEFAULT_FETCH_MODE | ||
*: <code>PDOStatement::fetch</code>メソッドや<code>PDOStatement::fetchAll</code> | *: SELECT結果を連想配列で取得できる。 | ||
*: | *: キーがカラム名になるため、データアクセスが直観的になる。 | ||
*: <br> | |||
*: <code>PDOStatement::fetch</code>メソッドや<code>PDOStatement::fetchAll</code>メソッドで引数が省略された場合、 | |||
*: または、ステートメントが<code>foreach</code>文に直接かけられた場合のフェッチスタイルを設定する。 | |||
*: 初期値は、<code>PDO::FETCH_BOTH</code>である。 | *: 初期値は、<code>PDO::FETCH_BOTH</code>である。 | ||
** PDO::FETCH_BOTH | ** PDO::FETCH_BOTH | ||
| 225行目: | 285行目: | ||
*: データベース側が持つプリペアドステートメント機能のエミュレーションをPDO側で行うかどうかを設定する。 | *: データベース側が持つプリペアドステートメント機能のエミュレーションをPDO側で行うかどうかを設定する。 | ||
*: PHP 5.2以降の初期値は<code>true</code>である。 | *: PHP 5.2以降の初期値は<code>true</code>である。 | ||
*: <br> | |||
*: <code>false</code>の場合、ネイティブのプリペアドステートメントを使用する。 | |||
*: これは、SQLインジェクション対策として有効であり、また、クエリのパフォーマンスが向上する。 | |||
*: <br> | |||
*: この設定は、いくつかPDOの挙動に違いが現れる。 | *: この設定は、いくつかPDOの挙動に違いが現れる。 | ||
** | *: エミュレーションを行う場合、プリペアドステートメントのためにデータベースと通信する必要が無くなるため、パフォーマンスは向上する。 | ||
* | *: 存在しないテーブル名 / カラム名をクエリに持つプリペアドステートメントを発行する場合、 | ||
*: エミュレーションを行わない場合は即エラーが発生するが、エミュレーションを行う場合はクエリを実行するまでエラーが発生するかどうかわからない。 | |||
** エミュレーションを行う場合のみ、<code>;</code>(セミコロン)区切りで複数のクエリを1つのクエリで実行することができる。 | ** エミュレーションを行う場合のみ、<code>;</code>(セミコロン)区切りで複数のクエリを1つのクエリで実行することができる。 | ||
*: <br> | *: <br> | ||
* PDO:: | * PDO::ATTR_PERSISTENT (コンストラクタでの指定のみ) | ||
*: <code>true</code>の場合、PHPスクリプトが終了してもデータベースへの接続を維持して、次回に再利用する。 | *: <code>true</code>の場合、PHPスクリプトが終了してもデータベースへの接続を維持して、次回に再利用する。 | ||
*: 特に、大規模システムでは恩恵が大きい。 | *: 特に、大規模システムでは恩恵が大きい。 | ||
*: <br> | |||
*: <code>false</code>の場合は、持続的な接続を無効化する。 | |||
*: メモリ管理の観点から、通常は無効にすることを推奨する。 | |||
*: <br> | *: <br> | ||
* PDO::MYSQL_ATTR_USE_BUFFERED_QUERY(MySQL専用) | * PDO::MYSQL_ATTR_USE_BUFFERED_QUERY(MySQL専用) | ||
| 247行目: | 315行目: | ||
* PDO::MYSQL_ATTR_INIT_COMMAND(MySQL専用、コンストラクタでの指定のみ) | * PDO::MYSQL_ATTR_INIT_COMMAND(MySQL専用、コンストラクタでの指定のみ) | ||
*: データベースに接続した直後に実行されるクエリをここに記述する。 | *: データベースに接続した直後に実行されるクエリをここに記述する。 | ||
*: <br> | |||
* PDO::ATTR_CASE | |||
*: <code>PDO::CASE_LOWER</code>を指定する場合、カラム名を小文字に統一する。 | |||
*: そのため、一貫性のあるコーディングが可能になる。 | |||
<br> | <br> | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
| 306行目: | 378行目: | ||
<u>データベースに接続できない場合等は、Warningが発生する。</u><br> | <u>データベースに接続できない場合等は、Warningが発生する。</u><br> | ||
<u>もし、データベースを動的に指定する場合、<code>set_error_handler</code>関数を使用して<code>ErrorException</code>に変換した後、例外処理を行う。</u><br> | <u>もし、データベースを動的に指定する場合、<code>set_error_handler</code>関数を使用して<code>ErrorException</code>に変換した後、例外処理を行う。</u><br> | ||
<br> | |||
==== 文字コードの設定 ==== | |||
<u>PDOでMySQLに接続する場合は、文字コードの設定 (例: charset=utf8mb4) を指定することを強く推奨する。</u><br> | |||
<br> | |||
もし、明示的に指定しない場合、MySQLのデフォルト設定に依存することになり、環境によって動作が異なる可能性がある。<br> | |||
そのため、確実な文字エンコーディングの制御のために、charsetを明示的に指定することを推奨する。<br> | |||
<br> | |||
* 絵文字や特殊文字のサポート | |||
*: utf8mb4は絵文字やその他の4バイト文字を完全にサポートする。 | |||
*: 通常のutf8では絵文字などが正しく保存できない可能性がある。 | |||
*: <br> | |||
* 文字化け防止 | |||
*: 日本語を含む多言語対応において、文字化けを防ぐことができる。 | |||
*: データベースとアプリケーション間で一貫した文字エンコーディングを保証する。 | |||
*: <br> | |||
* 将来の互換性 | |||
*: 現代のWebアプリケーションでは、utf8mb4が事実上の標準となっている。 | |||
*: 後々データベースに絵文字等を格納する可能性を考慮すると、最初から設定しておくのが無難である。 | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$db = new PDO('mysql:host=<IPアドレスまたはホスト名>;dbname=<データベース名>;charset=utf8mb4', '<ユーザ名>', '<パスワード>'); | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
| 335行目: | 432行目: | ||
データベースの接続は、PHPスクリプトが終了しても閉じられずにキャッシュされ、他のPHPスクリプトが同じ内容の接続を要求する時に再利用される。<br> | データベースの接続は、PHPスクリプトが終了しても閉じられずにキャッシュされ、他のPHPスクリプトが同じ内容の接続を要求する時に再利用される。<br> | ||
このキャッシュにより、新しい接続を確立するオーバーヘッドを避けることができるため、Webアプリケーションを高速化できるようになる。<br> | このキャッシュにより、新しい接続を確立するオーバーヘッドを避けることができるため、Webアプリケーションを高速化できるようになる。<br> | ||
<br> | |||
もし、明示的に閉じる場合、作成したPDOクラスのオブジェクトにNULLを代入する。<br> | |||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
<?php | <?php | ||
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, | try | ||
{ | |||
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, | |||
[ | |||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, | |||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC | |||
]); | |||
foreach($dbh->query('SELECT * from FOO') as $row) | |||
{ | |||
print_r($row); | |||
} | |||
} | |||
catch (PDOException $e) | |||
{ | { | ||
print('Connection failed:'.$e->getMessage()); | |||
} | die(); | ||
} | |||
// データベースの切断 | // データベースの切断 | ||
$dbh = null; | $dbh = null; | ||
?> | ?> | ||
| 500行目: | 606行目: | ||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||
// トランザクション開始 | |||
$dbh->beginTransaction(); | $dbh->beginTransaction(); | ||
// SQLクエリの実行 | |||
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')"); | $dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')"); | ||
$dbh->exec("insert into salarychange (id, amount, changedate) values (23, 50000, NOW())"); | $dbh->exec("insert into salarychange (id, amount, changedate) values (23, 50000, NOW())"); | ||
// 正常に実行できた場合はコミット | |||
$dbh->commit(); | $dbh->commit(); | ||
} | } | ||
catch(Exception $e) | catch(Exception $e) | ||
{ | { | ||
$dbh->rollBack(); | // エラーが発生した場合はロールバック | ||
if ($dbh->inTransaction()) { | |||
$dbh->rollBack(); | |||
} | |||
echo "失敗しました。" . $e->getMessage(); | echo "失敗しました。" . $e->getMessage(); | ||
} | } | ||
| 531行目: | 645行目: | ||
<br> | <br> | ||
プリペアドステートメントは、データベースの種類や機能に関わらず同じ仕組みで データベースへのアクセスができる。<br> | プリペアドステートメントは、データベースの種類や機能に関わらず同じ仕組みで データベースへのアクセスができる。<br> | ||
<br><br> | |||
== プリペアドステートメントの種類 == | |||
==== bindValueメソッド (値渡し) ==== | |||
* メリット | |||
*: バインドした後に元の変数が変更されても影響を受けない。 | |||
*: 直接リテラル値をバインドできる。 | |||
*: メモリ効率が良い。 (参照を保持しない) | |||
* デメリット | |||
*: ループ内で変数を変更して再実行する場合は、その都度、bindValueメソッドが必要となる。 | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
$value = 100; | |||
$stmt->bindValue(1, $value, PDO::PARAM_INT); | |||
$value = 200; // この変更はSQLに影響しない | |||
$stmt->execute(); // 100 が使用される | |||
</syntaxhighlight> | |||
<br> | |||
==== bindParamメソッド (参照渡し) ==== | |||
* メリット | |||
*: 変数の参照を保持するので、値を変更して再実行が容易 | |||
*: ストアドプロシージャのOUTパラメータで使用可能 | |||
* デメリット | |||
*: リテラル値を直接バインドできない。 | |||
*: メモリを若干多く使用する。 (参照を保持するため) | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
$value = 100; | |||
$stmt->bindParam(1, $value, PDO::PARAM_INT); | |||
$value = 200; // この変更がSQLに反映される | |||
$stmt->execute(); // 200 が使用される | |||
</syntaxhighlight> | |||
<br> | |||
==== executeメソッドで直接記述 ==== | |||
* メリット | |||
*: コードが簡潔 | |||
*: 1回のみ使用する場合は効率的 | |||
*: <br> | |||
* デメリット | |||
*: 変数の値を後から変更して再実行する場合は、その都度配列を作る必要がある。 | |||
*: 参照渡しができない。 | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
$stmt = $pdo->prepare("UPDATE student SET id = ?, name = ?, grade = ? WHERE id = ?"); | |||
$stmt->execute([$id, $name, $grade, $old_id]); // シンプル! | |||
## 1回限りのクエリの場合、executeメソッド | |||
$stmt->execute([$id, $name, $grade]); | |||
</syntaxhighlight> | |||
<br> | |||
==== 使い分け ==== | |||
<syntaxhighlight lang="php"> | |||
# 使い分け | |||
## 一般的なケースでは、bindValueメソッドを使用 | |||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); | |||
$stmt->bindValue(1, $id, PDO::PARAM_INT); | |||
$stmt->execute(); | |||
## 以下に示す場合は、bindParamメソッドを使用 | |||
## ループ内で値を変更しながら実行する場合 | |||
## ループ内で変数を変更しながら再実行する場合 | |||
## ストアドプロシージャのOUTパラメータを使用する場合 | |||
## 特別な理由で参照渡しが必要な場合 | |||
$stmt = $pdo->prepare("INSERT INTO logs (user_id, action) VALUES (?, ?)"); | |||
$stmt->bindParam(1, $user_id, PDO::PARAM_INT); | |||
$stmt->bindParam(2, $action, PDO::PARAM_STR); | |||
foreach($actions as $action) { | |||
$stmt->execute(); // $actionの値が自動的に使用される | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<u>セキュリティが重要な場合は、型を明示的に指定できるbindValueメソッド、または、bindParamメソッドを使用する。</u><br> | |||
<br> | |||
<u>※注意</u><br> | |||
<u>ただし、実務では一貫性を保つため、特別な理由がない限りどちらか一方に統一することが推奨される。</u><br> | |||
<br><br> | <br><br> | ||
| 814行目: | 1,005行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> | ||
{{#seo: | |||
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki | |||
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 | |||
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux | |||
|image=/resources/assets/MochiuLogo_Single_Blue.png | |||
}} | |||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:Web]] | [[カテゴリ:Web]][[カテゴリ:MySQL]] | ||