PHP-DB - 8. レコードのフェッチ

それではPDOライブラリについて詳細に学習していきましょう。まずはじめにレコードのフェッチについて取り上げます。

プログラミングの文脈においてこのフェッチ( fetch )という言葉には「データを取りに行く(引き出す)」という意味合いがあります。ここではデータベースに対して select 文を発行し、その結果であるデータを取りに行くという具合です。

これまでに学習してきたとおり、 select 文を実行するには PDO クラスの query メソッドを呼び出して、 PDOStatement インスタンスを取得し、 PDOStatement クラスの fetch メソッドや fetchAll メソッドによって検索結果をフェッチします。このとき fetch メソッド( fetchAll メソッド)の引数に、 PDO クラスの定数(フェッチモード)を指定することで、でデータの取得方法をカスタマイズできます。

PDOのフェッチモード

フェッチモード 意味
PDO::FETCH_NUM 要素番号によるアクセスのみ
PDO::FETCH_ASSOC カラム名によるアクセスのみ
PDO::FETCH_BOTH 要素番号、カラム名の両方のアクセス(引数を省略した場合のデフォルト)
PDO::FETCH_OBJ 戻り値を配列ではなくオブジェクトで返却する

ここではフェッチモードの仕組みを学習するために、次のプログラム( pdo6.php )を作成してみましょう。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

$row = $st->fetch();
// $row = $st->fetch(PDO::FETCH_NUM);
// $row = $st->fetch(PDO::FETCH_ASSOC);
// $row = $st->fetch(PDO::FETCH_BOTH);
// $row = $st->fetch(PDO::FETCH_OBJ);

var_dump($row);

ここではいくつかのステートメントをコメントアウトしています。コメントアウトしている部分では fetch メソッドの引数にフェッチモードを指定しています。まずは fetch メソッドの引数を省略した場合のデフォルトの振る舞いについて確認してみましょう。

コマンドラインからプログラムを実行します。

$ php pdo6.php
array(4) {
  ["id"]=>
  string(1) "1"
  [0]=>
  string(1) "1"
  ["title"]=>
  string(11) "Programming"
  [1]=>
  string(11) "Programming"
}

実行結果はこれまでに学習してきたとおりです。 $st->fetch() の戻り値は連想配列となっており、列名と列番号(要素番号)がキーとなっているのがわかります。

PDO::FETCH_NUM を指定した場合

続いてフェッチモードに PDO::FETCH_NUM を指定してみましょう。プログラム( pdo6.php )を修正します。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

// $row = $st->fetch();
$row = $st->fetch(PDO::FETCH_NUM);
// $row = $st->fetch(PDO::FETCH_ASSOC);
// $row = $st->fetch(PDO::FETCH_BOTH);
// $row = $st->fetch(PDO::FETCH_OBJ);

var_dump($row);

fetch メソッド引数に PDO::FETCH_NUM を指定すると、戻り値に列番号(要素番号)だけをキーに持つ配列を取得できます。プログラムを実行すると次のようになります。

$ php pdo6.php
array(2) {
  [0]=>
  string(1) "1"
  [1]=>
  string(11) "Programming"
}

PDO::FETCH_ASSOC を指定した場合

続いてフェッチモードに PDO::FETCH_ASSOC を指定してみましょう。プログラム( pdo6.php )を修正します。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

// $row = $st->fetch();
// $row = $st->fetch(PDO::FETCH_NUM);
$row = $st->fetch(PDO::FETCH_ASSOC);
// $row = $st->fetch(PDO::FETCH_BOTH);
// $row = $st->fetch(PDO::FETCH_OBJ);

var_dump($row);

fetch メソッド引数に PDO::FETCH_ASSOC を指定すると、戻り値に列名だけをキーに持つ配列を取得できます。プログラムを実行すると次のようになります。

$ php pdo6.php
array(2) {
  ["id"]=>
  string(1) "1"
  ["title"]=>
  string(11) "Programming"
}

PDO::FETCH_BOTH を指定した場合

次にフェッチモードに PDO::FETCH_BOTH を指定してみましょう。プログラム( pdo6.php )を修正します。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

// $row = $st->fetch();
// $row = $st->fetch(PDO::FETCH_NUM);
// $row = $st->fetch(PDO::FETCH_ASSOC);
$row = $st->fetch(PDO::FETCH_BOTH);
// $row = $st->fetch(PDO::FETCH_OBJ);

var_dump($row);

fetch メソッド引数に PDO::FETCH_BOTH を指定すると、戻り値に列名と列番号(要素番号)をキーに持つ配列を取得できます。これは引数を省略した場合と同じ、デフォルトの振る舞いです。プログラムを実行すると次のようになります。

$ php pdo6.php
array(4) {
  ["id"]=>
  string(1) "1"
  [0]=>
  string(1) "1"
  ["title"]=>
  string(11) "Programming"
  [1]=>
  string(11) "Programming"
}

PDO::FETCH_OBJ を指定した場合

さいごにフェッチモードに PDO::FETCH_OBJ を指定してみましょう。プログラム( pdo6.php )を修正します。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

// $row = $st->fetch();
// $row = $st->fetch(PDO::FETCH_NUM);
// $row = $st->fetch(PDO::FETCH_ASSOC);
// $row = $st->fetch(PDO::FETCH_BOTH);
$row = $st->fetch(PDO::FETCH_OBJ);

var_dump($row);

fetch メソッド引数に PDO::FETCH_OBJ を指定すると、戻り値が配列ではなくオブジェクト( stdClass のインスタンス)となります。プログラムを実行すると次のようになります。

$ php pdo6.php
object(stdClass)#3 (2) {
  ["id"]=>
  string(1) "1"
  ["title"]=>
  string(11) "Programming"
}

この場合、戻り値が配列ではなくオブジェクト( stdClass のインスタンス)として返却されているので、テーブルの各列に対してプロパティ経由でアクセスできます。プログラム( pdo6.php )を次のように修正してみましょう。

<?php
$dsn = "sqlite:eldb.sqlite3";
$pdo = new PDO($dsn);

$sql = "select id, title from categories";
$st = $pdo->query($sql);

$rows = $st->fetchAll(PDO::FETCH_OBJ);

foreach ($rows as $row) {
  echo $row->id . ":" . $row->title .  PHP_EOL;
}

$row->id$row->title のようにプロパティ経由で検索結果にアクセスします。プログラムを実行すると次のようになります。

$ php pdo6.php
1:Programming
2:Design
3:Marketing

まとめ

  • PDOStatement インスタンスの fetch メソッド、 fetchAll メソッドの戻り値である配列は、要素番号によるアクセス、カラム名によるアクセスをサポートしている
  • これらのアクセス方法は fetch メソッド( fetchAll メソッド)の実行時に PDO クラスに用意されている定数によって変更できる
  • デフォルトのフェッチモードは PDO::FETCH_BOTH を指定した場合の動作となる