PHP-DB - 4. レコードの取得

PDOインスタンスを生成できたので、次はSQLを実行する方法を学習します。ここではまず select 文の実行方法について取り上げます。次のプログラム( pdo2.php )を作成してみましょう。

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

$sql = "select id, title from categories order by id";
$st = $pdo->query($sql);
$row = $st->fetch();
while ($row !== false) {
    echo $row["id"] . ":" . $row["title"] .  PHP_EOL;
    $row = $st->fetch();
}

このプログラムではまず PDO インスタンスを生成しています。

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

PDO インスタンスを生成した後、 $sql 変数 に select 文を文字列データとして代入し、 $pdo 変数に対して query メソッドを呼び出しています。このとき PDO クラスの query メソッドは戻り値に PDOStatement インスタンスを返却します。

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

PDOStatement クラスには検索結果にアクセスするための fetch メソッドや fetchAll メソッドが用意されています。 $st 変数に代入されている PDOStatement インスタンスに対してこれらのメソッドを呼び出すことで検索結果にアクセスできます。

このプログラムでは while 文と組み合わせて、 $st 変数に対して fetch メソッドを繰り返し呼び出すことで、検索結果を1行ずつ取得しています。

$row = $st->fetch();
while ($row !== false) {
    echo $row["id"] . ":" . $row["title"] .  PHP_EOL;
    $row = $st->fetch();
}

$st->fetch() メソッドの呼び出しは、デフォルトで検索結果から1行のデータを連想配列として返却します。この連想配列は select 文に指定した列名(と列番号)をキーとしています。ここでは $st->fetch() の戻り値を $row 変数に代入しているので、 $row["id"]$row["title"] として検索結果にアクセスできます。

また $st->fetch() メソッドの呼び出しは、検索結果の終端に達している時点で呼び出すと戻り値に false を返します。そのため while 文の条件式において $row 変数が false でないことを確認しています。

それではコマンドラインからプログラムを実行してみましょう。

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

表示された内容からSQL( select id, title from categories order by id ) の検索結果をPHPで処理できているのがわかります。

PDOStatement クラス - fetchAll メソッド

さきほどのプログラム( pdo2.php )では PDOStamenet インスタンスに対して、繰り返し fetch メソッドを呼び出すことで検索結果を処理しました。もう一つ、ここでは fetchAll メソッドを呼び出して検索結果を処理する方法を取り上げます。プログラム( pdo2.php )を次のように修正してみましょう。

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

$sql = "select id, title from categories order by id";
$st = $pdo->query($sql);
$rows = $st->fetchAll();
foreach ($rows as $row) {
    echo $row["id"] . ":" . $row["title"] .  PHP_EOL;
}

PDOStatement クラスの fetchAll メソッドを呼び出すことで select 文の実行結果を2次元配列で取得できます。ここでは $st->fetchAll() メソッドを呼び出しているので、 $rows 変数には2次元配列が代入されます。そのため foreach 構文を使って 2次元配列 $rows の中の要素を $row 変数 に代入して繰り返し処理しています。 $row 変数には列名(と列番号)をキーにした連想配列が代入されているので、 $row["id"]$row["title"] のように列名を指定して結果にアクセスできます。

コマンドラインからプログラムを実行してみましょう。

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

実行結果から $st->fetchAll() メソッドの呼び出しの結果を繰り返し処理できているのがわかります。

参考:列番号によるアクセス

PDOStatement クラスの fetch メソッドや fetchAll メソッドの戻り値に対して、列名でなく列番号でもアクセスできます。さきほどのプログラム( pdo2.php )において、 $st->fetchAll() 呼び出しの戻り値である2次元配列を print_r 関数で出力してみましょう。

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

$sql = "select id, title from categories order by id";
$st = $pdo->query($sql);
$rows = $st->fetchAll();
print_r($rows);

コマンドラインからプログラムを実行してみましょう。

$ php pdo2.php
Array
(
    [0] => Array
        (
            [id] => 1
            [0] => 1
            [title] => Programming
            [1] => Programming
        )

    [1] => Array
        (
            [id] => 2
            [0] => 2
            [title] => Design
            [1] => Design
        )

    [2] => Array
        (
            [id] => 3
            [0] => 3
            [title] => Marketing
            [1] => Marketing
        )
)

実行結果から、検索結果として3件のレコードが返却されているのがわかります。また各レコードを表す連想配列のキーには列名( "id""title" )以外にはも 01 といった番号もキーに含まれているのがわかります。

そのため、次のように列名ではなく列番号を指定して検索結果にアクセスできます。プログラム( pdo2.php )を修正してみましょう。

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

$sql = "select id, title from categories order by id";
$st = $pdo->query($sql);
$rows = $st->fetchAll();
foreach ($rows as $row) {
    echo $row[0] . ":" . $row[1] .  PHP_EOL;
}

ここでは echo $row[0] . ":" . $row[1] . PHP_EOL; のように列名ではなく列番号を指定しています。この場合、 "id" 列にアクセスするには列番号 0"title" 列にアクセスするには列番号 1 でアクセスできます。

コマンドラインからプログラムを実行してみましょう。

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

実行結果から列番号による指定も正しく動作していることがわかります。

まとめ

  • PDO インスタンスの query メソッドによって select 文を実行する
  • query メソッドの戻りには PDOStatement インスタンスが返却される
  • PDOStatement インスタンスの fetch メソッドや fetchAll メソッドを呼び出すことで select 文の実行結果にアクセスできる