【PHP8.x】PDOStatement::fetch()メソッドの使い方
fetchメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
fetchメソッドは、PHPのデータベース操作拡張であるPDOにおいて、SQLクエリの実行結果から次の行を取得するメソッドです。
データベースに対するクエリが実行され、結果がPDOStatementオブジェクトに格納された後、このfetchメソッドが使用されます。メソッドが呼び出されるたびに、結果セットの中から次の1行分のデータが取り出され、内部のカーソルは自動的にその次の行へと進みます。これにより、大量のデータベース結果を一度にメモリに読み込むことなく、効率的にデータを1行ずつ順次処理することが可能になります。
fetchメソッドは、取得したデータを、PDOStatementオブジェクトにあらかじめ設定されたフェッチスタイル(例えば、数値添字配列、連想配列、またはオブジェクト形式など)に従って返します。結果セット内のすべての行が取得され尽くすと、このメソッドはfalseを返します。この特性を利用して、通常はwhileループの中でfetchメソッドを繰り返し呼び出すことで、データベースから取得したすべてのデータを順番に処理し、アプリケーション内で利用する際に非常に重要な役割を果たします。データベースから情報を取得し、表示したり加工したりする際の基本的な処理として幅広く利用されています。
構文(syntax)
1<?php 2$row = $pdoStatement_instance->fetch(PDO::FETCH_ASSOC);
引数(parameters)
int $mode = PDO::FETCH_DEFAULT, int $cursorOrientation = PDO::FETCH_ORI_NEXT, int $cursorOffset = 0
- int $mode = PDO::FETCH_DEFAULT: 取得する行の形式を指定する整数。デフォルトは PDO::FETCH_DEFAULT です。
- int $cursorOrientation = PDO::FETCH_ORI_NEXT: カーソルの向きを指定する整数。デフォルトは PDO::FETCH_ORI_NEXT です。
- int $cursorOffset = 0: カーソルのオフセットを指定する整数。デフォルトは 0 です。
戻り値(return)
mixed
PDOStatement::fetchメソッドは、データベースから次の1行のレコードをフェッチします。取得するレコードがない場合はfalseを返します。
サンプルコード
PDOStatement::fetch で1行ずつ取得する
1<?php 2 3// エラー報告を有効にし、すべてのエラーを表示 4ini_set('display_errors', 1); 5ini_set('display_startup_errors', 1); 6error_reporting(E_ALL); 7 8/** 9 * PDOStatement::fetch メソッドの使用例を示します。 10 * メモリ内SQLiteデータベースを使用し、データの作成、挿入、取得を行います。 11 * システムエンジニアを目指す初心者向けに、結果セットから行をフェッチする方法を簡潔に示します。 12 */ 13function runPdoFetchExample(): void 14{ 15 // メモリ内SQLiteデータベースを使用 (ファイルを作成しないため手軽に試せます) 16 $dsn = 'sqlite::memory:'; 17 $user = null; // SQLiteではユーザー名/パスワードは不要 18 $password = null; 19 20 try { 21 // データベースに接続 22 // PDO::ATTR_ERRMODE を PDO::ERRMODE_EXCEPTION に設定すると、エラー発生時にPDOExceptionをスローします。 23 // PDO::ATTR_DEFAULT_FETCH_MODE を PDO::FETCH_ASSOC に設定すると、デフォルトで結果を連想配列として取得します。 24 $pdo = new PDO($dsn, $user, $password, [ 25 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 26 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 27 ]); 28 29 // テーブルを作成 (既に存在する場合は何もしない) 30 $pdo->exec(" 31 CREATE TABLE IF NOT EXISTS products ( 32 id INTEGER PRIMARY KEY AUTOINCREMENT, 33 name TEXT NOT NULL, 34 price REAL NOT NULL 35 ); 36 "); 37 38 // テストデータを挿入 39 // プリペアドステートメントを使用することで、SQLインジェクション攻撃を防ぎます。 40 $stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (:name, :price)"); 41 $stmt->execute([':name' => 'Laptop', ':price' => 1200.00]); 42 $stmt->execute([':name' => 'Mouse', ':price' => 25.50]); 43 $stmt->execute([':name' => 'Keyboard', ':price' => 75.00]); 44 45 echo "--- PDOStatement::fetch を使った商品の取得 ---\n"; 46 47 // 全ての商品のデータを取得するクエリを実行 48 $stmt = $pdo->query("SELECT id, name, price FROM products"); 49 50 // PDOStatement::fetch をループで呼び出し、結果セットから1行ずつデータを取得します。 51 // 引数 PDO::FETCH_ASSOC は、結果をカラム名をキーとする連想配列として取得するモードです。 52 // キーワード "php fetchall" に関連して、fetch は1行ずつ取得するのに対し、 53 // 全ての行を一度に配列として取得したい場合は、PDOStatement::fetchAll メソッドも利用できます。 54 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 55 echo "ID: " . $row['id'] . ", Name: " . $row['name'] . ", Price: " . $row['price'] . "\n"; 56 } 57 58 } catch (PDOException $e) { 59 // データベース接続またはクエリ実行でエラーが発生した場合 60 echo "データベースエラー: " . $e->getMessage() . "\n"; 61 } 62} 63 64// サンプル関数を実行 65runPdoFetchExample();
PDOStatement::fetch メソッドは、データベースのクエリ結果セットから「次の1行」を順に取得するために使用されます。このサンプルコードでは、メモリ内SQLiteデータベースに接続し、productsテーブルを作成してテストデータを挿入しています。
その後、SELECTクエリを実行してPDOStatementオブジェクトを取得し、whileループ内で$stmt->fetch(PDO::FETCH_ASSOC)を繰り返し呼び出しています。ここで$mode引数に指定されているPDO::FETCH_ASSOCは、取得する行データをカラム名をキーとする連想配列として返すモードです。通常、$cursorOrientationや$cursorOffsetはデフォルト値が使われます。
fetchメソッドは、取得できた行データがあればその連想配列を戻り値として返し、もう取得すべき行がない場合はfalseを返します。この挙動を利用して、サンプルではfalseが返されるまでループを継続し、結果セットのすべての行を1つずつ画面に表示しています。
キーワード「php fetchall」に関連して、fetchが結果セットから1行ずつデータを取得するのに対し、PDOStatement::fetchAllメソッドは、結果セットの全行を一度に配列として取得したい場合に利用されます。データベースとの接続やクエリ実行中にエラーが発生した場合は、try-catchブロックでPDOExceptionが捕捉され、エラーメッセージが表示されるようになっています。
PDOStatement::fetchは、データベースの結果セットから行を1行ずつ取得するメソッドです。サンプルではPDO::FETCH_ASSOCを指定し、カラム名をキーとする連想配列として行を取得していますが、PDO::FETCH_NUMやPDO::FETCH_OBJなど取得形式を選べます。行がなくなるとfalseを返すため、whileループで簡単に全行を処理できます。全ての行を一度に配列として取得したい場合はfetchAllメソッドも利用できますが、データ量が多い場合はメモリ使用量に注意が必要です。エラー処理のためのtry-catchブロックとPDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTIONの設定、そしてSQLインジェクションを防ぐプリペアドステートメントの使用は、安全なデータベース操作の基本ですので必ず実践してください。
PDOStatement::fetch(PDO::FETCH_ASSOC)で結果を連想配列として取得する
1<?php 2 3/** 4 * データベースからユーザー情報を取得し、連想配列として表示するサンプルコード。 5 * PDO::FETCH_ASSOC モードを使用し、結果をカラム名をキーとする連想配列で取得します。 6 */ 7function fetchUsersAsAssocArray(): void 8{ 9 // データベース接続情報 (SQLiteのインメモリデータベースを使用) 10 $dsn = 'sqlite::memory:'; 11 $username = null; 12 $password = null; 13 14 try { 15 // PDO (PHP Data Objects) インスタンスを作成し、データベースに接続 16 // エラー発生時に例外をスローするように設定 (PDO::ERRMODE_EXCEPTION) 17 $pdo = new PDO($dsn, $username, $password, [ 18 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 19 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // デフォルトのフェッチモードを設定 20 ]); 21 22 echo "データベースに接続しました。\n\n"; 23 24 // サンプルテーブルの作成 25 $pdo->exec(" 26 CREATE TABLE IF NOT EXISTS users ( 27 id INTEGER PRIMARY KEY AUTOINCREMENT, 28 name TEXT NOT NULL, 29 email TEXT UNIQUE NOT NULL 30 ); 31 "); 32 echo "テーブル 'users' を作成しました。\n"; 33 34 // サンプルデータの挿入 35 $pdo->exec("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');"); 36 $pdo->exec("INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');"); 37 echo "サンプルデータを挿入しました。\n\n"; 38 39 // データの取得 (プリペアドステートメントを使用) 40 $sql = "SELECT id, name, email FROM users WHERE id > :min_id"; 41 $stmt = $pdo->prepare($sql); 42 43 // プレースホルダに値をバインド 44 $minId = 0; 45 $stmt->bindParam(':min_id', $minId, PDO::PARAM_INT); 46 47 // ステートメントを実行 48 $stmt->execute(); 49 50 echo "ユーザー情報:\n"; 51 echo "---------------------------------\n"; 52 53 // PDOStatement::fetch メソッドで一行ずつ結果を取得 54 // PDO::FETCH_ASSOC を指定することで、結果を連想配列として取得します。 55 // キーはカラム名になります。 56 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 57 echo "ID: " . $row['id'] . "\n"; 58 echo "名前: " . $row['name'] . "\n"; 59 echo "Email: " . $row['email'] . "\n"; 60 echo "---------------------------------\n"; 61 } 62 63 echo "すべてのユーザー情報を取得しました。\n"; 64 65 } catch (PDOException $e) { 66 // データベース関連のエラーが発生した場合 67 echo "データベースエラー: " . $e->getMessage() . "\n"; 68 } catch (Exception $e) { 69 // その他のエラーが発生した場合 70 echo "一般エラー: " . $e->getMessage() . "\n"; 71 } finally { 72 // PDOオブジェクトをクローズ (通常はスクリプト終了時に自動で解放される) 73 // 明示的にnullを代入することで接続を閉じることができる 74 $pdo = null; 75 echo "\nデータベース接続を閉じました。\n"; 76 } 77} 78 79// 関数を実行 80fetchUsersAsAssocArray(); 81 82?>
PHPのPDOStatement::fetchメソッドは、データベースから実行したクエリの結果セットの中から、次の1行のデータを一つずつ取り出すための重要な機能です。このメソッドは通常、whileループ内で使用され、取得したすべての結果行を順に処理する際に利用されます。
引数 $mode には、取得するデータをどのような形式で受け取るかを指定します。サンプルコードではPDO::FETCH_ASSOCを指定しており、これはデータベースのカラム名(列名)をキーとする連想配列として結果を取得することを意味します。例えば、idやnameといったカラム名がそのまま連想配列のキーとなり、$row['id']のように値にアクセスできるため、データの意味が直感的にわかりやすくなります。
オプションの引数である$cursorOrientationと$cursorOffsetは、結果セット内のカーソル(現在の読み込み位置)を操作する際に使用しますが、通常はデフォルト値が使われ、次の行を順次取得します。
このメソッドの戻り値はmixed型で、指定されたフェッチモードに応じた1行分のデータ(PDO::FETCH_ASSOCの場合は連想配列)を返します。もし、もう取得できるデータが結果セット内に存在しない場合は、falseが返されます。サンプルコードでは、このfalseがwhileループの終了条件として利用され、すべてのユーザー情報を取得し終えるとループが終了します。PDO::FETCH_ASSOCは、データベースのテーブル構造と対応する分かりやすい形でデータが扱えるため、特に初心者にとって理解しやすいフェッチモードです。
このサンプルコードでは、データベースから一行ずつデータを取得するPDOStatement::fetchメソッドが使われています。特にPDO::FETCH_ASSOCを指定すると、結果がカラム名をキーとした連想配列になるため、データの参照時には正確なカラム名を指定してください。もしデータが存在しない場合はfalseが返されますので、whileループの終了条件として適切に利用されています。SQLインジェクション対策としてプリペアドステートメントとbindParamを使っている点は非常に重要です。常にこの方法でクエリを実行し、セキュリティを確保してください。また、PDO::ATTR_ERRMODEをPDO::ERRMODE_EXCEPTIONに設定し、try-catchブロックでエラーを捕捉することは、堅牢なアプリケーション開発に不可欠です。データベース接続はスクリプト終了時に自動解放されますが、明示的に$pdo = null;で閉じることもできます。