質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

PHP fetchAll

受付中

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 1,305

marimokomokmOk

score 50

以下のコードは、
executeメソッドで実行した結果はfetchAllで
取得していないのですが、よろしいのでしょうか。
executeメソッドで実行した結果はfetchAllで
取得と学びました。

if(isset($_POST['command']) || !$_POST){
    switch($_POST['command']){
    case 'update':
        $sql = $pdo->prepare('update words set word=?, sense=?, memo=? where id=?');
        $sql -> execute(array(h($_POST['word']),h($_POST['sense']),h($_POST['memo']),$_POST['id']));
        break;
    case 'delete':
        $sql = $pdo->prepare('delete from words where id=?');
        $sql->execute(array($_POST['id']));
        break;
    case 'insert':
        $sql = $pdo->prepare('insert into words values(null,?,?,?)');
        $sql->execute(array(h($_POST['word']),h($_POST['sense']),h($_POST['memo'])));
        break;
    case 'listDisplay':
        break;
    }
        foreach ($pdo->query('select * from words order by id desc') as $row){
        echo '<tr>';
//         echo '<td width="30"  height="35" align="center" width="110" height="35">', h($row['id']), '</td>';
        echo '<td width="30" class="font3"><b>', h($row['word']), '</b></td>';
        echo '<td width="150" class="font3">', h($row['sense']), '</td>';
        echo '<td width="150" class="font3">', h($row['memo']), '</td>';
        echo '</tr>';
        echo "\n";
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

PHP: PDO::query - Manual

結果セットのPDOStatement型データを返すので、
それを一行ずつ$rowに格納してforeach()ループで一行ずつ読み出しているので問題ありません。

一度に結果全行を読み出すのと、
結果一行ずつすべて読むのとどう違うかというと、
全行読み出すとき結果のレコード数が数千数万だったりすると、
結果を溜め込むまで一見処理が止まってしまいます。
(メモリ的リソースもきつくなります。)
一行ずつ読み出すと、順々にHTML出力ができて止まらず出力し続けられます。
(溜め込まないため軽く動かせるはず。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/24 17:21 編集

    m6u様

    レスありがとうございます。

    > mysqliにある説明って、PDO接続でも同じ話なんでしょうかね

    同じ話ですよ。
    mysqli も PDO_MySQL も(そして mysql も)、内部では同じライブラリを使用していますので。

    http://php.net/manual/ja/mysqlinfo.library.choosing.php
    > mysqli、PDO_MySQL、そして mysql といった PHP 拡張モジュールは、 どれも C クライアントライブラリの軽量なラッパーです。これらの拡張モジュールは、 mysqlnd ライブラリあるいは libmysqlclient ライブラリのいずれかを使えます。

    PDO_MySQL の場合、非バッファクエリを使用するか否かは
     PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
    という属性で切り替えることができます。

    http://php.net/manual/ja/ref.pdo-mysql.php#pdo-mysql.constants
    > PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (integer)
    PDOStatement でこの属性を TRUE に設定すると、 MySQL ドライバはバッファ版の MySQL API を使用します。


    ちなみに、
    > この属性を TRUE に設定すると、

    などと、あたかもデフォルト値が FALSE であるかのように書いてありますが、
    私の手元の環境 (Mac OSX 10.9) で確認した限りでは、デフォルトは TRUE でしたw

    キャンセル

  • 2017/02/24 17:48

    KiyoshiMotokiさん、丁寧にありがとうございます。稚拙な回答申し訳ありません。

    キャンセル

  • キャンセル

+1

foreachで回すときは事前に$pdoにオプションでassocの設定を
しておいた方がよいでしょう

$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

以下のコードは、 
executeメソッドで実行した結果はfetchAllで 
取得していないのですが、よろしいのでしょうか。

問題ありません。

foreach ($pdo->query('select * from words order by id desc') as $row){
   ...
}


上のコードは、以下のコードと同じ意味になります。
(全く同じコードに変換・実行されているとは限りません)

$stmt = $pdo->query('select * from words order by id desc');
while (($row = $stmt->fetch()) !== false){
   ...
}


そして、PDO の設定や使用する DB の種類によって内部的な動作は異なる可能性がありますが、
実行結果は、以下のコードとも同じになります。

$stmt = $pdo->query('select * from words order by id desc');
foreach ($stmt->fetchAll() as $row){
   ...
}

なぜ

foreach ($pdo->query('...') as $row)


というコードが

while (($row = $stmt->fetch()) !== false)


と同じ意味になるかと言うと、$pdo->query('...')の戻り値である PDOStatement型が、
Traversableインターフェースをそのように実装しているからです。
http://php.net/manual/ja/class.pdostatement.php

PDOStatement implements Traversable {

http://php.net/manual/ja/class.traversable.php

そのクラスの中身が foreach を使用してたどれるかどうかを検出するインターフェイスです。

もっとも、実際、どのように PDOStatement型が Traversableインターフェースを実装しているか確認するため
ソースコードを読んでみようとしましたが、難しすぎて私にはお手上げでしたw
https://github.com/php/php-src/blob/master/ext/pdo/pdo_stmt.c

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/03 15:22

    ご解答下さりありがとうございます。
    $stmt = $pdo->query('select * from words order by id desc');
    foreach ($stmt->fetchAll() as $row){
    ...
    }
    まだ理解できてないので考えて見ます。
    ご解答内容が難しくてついていけません。
    考えて見ます。

    キャンセル

  • 2017/03/03 16:02

    Good Luck

    キャンセル

  • 2017/03/03 16:45

    難しいですね><
    25歳のときはできてましたか?
    私、もう25歳で未だに会社でPHP実務できてないです...><
    みんなそういう不吉なときがあるんでしょうか。

    キャンセル

  • 2017/03/03 17:47

    25歳の頃、私はまだ学生でした。
    つまり、PHP という言語があることすら知りませんでした。

    走る速さは人それぞれであるように、
    スキルを習得する速さも人それぞれです。

    あきらめずに勉強を続ければ、少なくとも前に進むことはできます。

    がんばって下さい。

    キャンセル

+1

例に挙げられたプログラムですと、execute() を使っているのは INSERT, UPDATE, DELETE です。
SELECT 以外の SQL を投げた場合、結果セットがありません。
※結果(行数)はありますが、結果セットにはなりません
なので fetch は不要というか、呼び出す意味がありません。

ただ、実運用においては update において、適用が0行だった場合を失敗と見なしたいこともあるので、そのような場合は rowCount() を取って判断します。
※update で対象が 0 件の場合は SQL は成功しているので、成功/失敗で判定できない

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/03 13:39

    ありがとうございます。
    SELECTは選ぶので選んだ値を結果セットで返すんですね

    キャンセル

  • 2017/03/03 13:48

    すみません。
    まだ理解できてないです。
    もう少し考えます。

    キャンセル

  • 2017/03/03 14:46

    execute したら fetchAll する、というのが間違いです。
    SELECT したら fetch か fetchAll を使う、です。
    逆に SELECT 以外を投げたときは、query() で投げようが execute() で投げようが、fetch する必要がありません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る