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

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

新規登録して質問してみよう
ただいま回答率
85.48%
PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

4回答

3012閲覧

PHP fetchAll

marimokomokmOk

総合スコア52

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2017/02/24 07:35

以下のコードは、
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"; } }

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

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

投稿2017/03/02 04:11

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marimokomokmOk

2017/03/03 04:39

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

2017/03/03 04:48

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

2017/03/03 05:46

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

0

以下のコードは、

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

問題ありません。

php

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

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

php

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

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

php

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

なぜ

php

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

というコードが

php

1while (($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/02 03:27

KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marimokomokmOk

2017/03/03 06:22

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

2017/03/03 07:45

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

2017/03/03 08:47

25歳の頃、私はまだ学生でした。 つまり、PHP という言語があることすら知りませんでした。 走る速さは人それぞれであるように、 スキルを習得する速さも人それぞれです。 あきらめずに勉強を続ければ、少なくとも前に進むことはできます。 がんばって下さい。
guest

0

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

PHP

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

投稿2017/02/24 08:45

yambejp

総合スコア114779

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

PHP: PDO::query - Manual

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

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

投稿2017/02/24 07:40

編集2017/02/24 07:43
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marimokomokmOk

2017/02/24 07:52

executeメソッドで実行した結果はfetchAllで 取得しなくてもいいんですね。 なるほど、難しいですね。 fetchAllは一度に全部の結果行を取得するからメモリ的にもきついんですね。
退会済みユーザー

退会済みユーザー

2017/02/24 07:58

[PHP: PDOStatement::fetch - Manual](http://php.net/manual/ja/pdostatement.fetch.php) を使うよりもシンプルな記述になるので好まれる傾向があります。 ただし、結果が十分少なくて一度に読み込んだほうがラクな場合もあるでしょうから、臨機応変で使い分けましょう。 (一度に数千数万取得することがまず起こらないように、SELECT文にLIMITやOFFSETをつけることもあるでしょうから。)
KiyoshiMotoki

2017/02/24 08:00 編集

横から失礼します。 > 一行ずつ読み出すと、順々にHTML出力ができて止まらず出力し続けられます。 については、DB の種類とドライバの設定によりますよ。 例えば MySQL の場合、デフォルトの設定ではクエリを実行した時点で全てのデータが PHP に送信されます。 http://php.net/manual/ja/mysqlinfo.concepts.buffering.php > クエリは、デフォルトではバッファモードで実行されます。 つまり、クエリの結果がすぐに MySQL サーバーから PHP に転送され、 PHP プロセスのメモリ内に結果を保持し続けるということです。 PostgreSQL の場合、公式のドキュメントの記述は見つけられませんでしたが、 stackoverflow では 「非バッファクエリは使用できない」 という結論になっています。 http://stackoverflow.com/a/1891929/6299234 > Unfortunately there is not an unbuffered mode for the PHP pgsql extension or the pdo_pgsql extension.
退会済みユーザー

退会済みユーザー

2017/02/24 08:10

KiyoshiMotokiさん、ご指摘ありがとうございます。 mysqliにある説明って、PDO接続でも同じ話なんでしょうかね、PDO側のマニュアルに該当する記述が見つけられず、どっちなのか今ひとつわかりかねます。 大方、結果を全行PHP側に渡してしまって(バッファクエリ)、でもPHP内で全行フルに触るfetchAll()と一行ずつ処理するfetch()、場面に合わせて使えますよということであまりパフォーマンス面の意図はないと考えていいんですかね。
KiyoshiMotoki

2017/02/24 08:24 編集

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 08:48

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問