Help us understand the problem. What is going on with this article?

PHP SQL P198 忘れがちな箇所をお浚い

More than 1 year has passed since last update.

PHPから

all2.php
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {
    echo '<p>';
    echo $row ['id'], ':';
    echo $row ['name'], ':';
    echo $row ['price'];
    echo '</p>';
}
var_dump ( $pdo );
?>

PHPからselect文の実行

2017030701.png

$pdo->query ( 'select * from product' )

メソッドを呼び出すには「変数->メソッド」のように
->」を使って記述する。


取得したデータを1行ずつ処理する

foreach ( $pdo->query ( 'select * from product' ) as $row ) {
・・・
}

データベースから取得したデータは複数行にわたる。
productテーブルを指定してselect文を実行すると複数行の商品データが返って来る。
複数行のデータを順に処理するにはforeachループのような繰り返し構文を使う必要がある。

queryメソッドとforeachループを組み合わせると複数行のデータを簡単に処理することができる。

  • 配列ではないのに何故_________________________________
    ・foreachは配列とオブジェクトをループして使うための構文。配列ではないが使いやすくするために 特別にforeachの反復処理で使えるように作られている。
    _________________________________________________________

query

  PHPからSQL文を実行
SQL文を実行 PDOの変数->query('SQL文')
メソッドを呼び出す 変数->メソッド
queryメソッド(関数) 引数に指定したSQL文をデータベースに対して実行する
->(アロー演算子) メソッドを呼び出す

ここではqueryメソッドによって取得された複数行のデータが1行ずつ順番に変数$rowに代入されます。
「・・・」の部分では、$rowを使って1行分のデータを取得し、表示するなどの処理を行います。


例$row['id']

指定した列のデータを取り出す

取得した行からidを取り出すには、
$row['id']
のように記述する。

1行分のデータは配列形式で格納されている。
列を取り出すには列名を配列の添字に指定する。

2017030702.png

取り出したid列のデータに「:」をつけて表示する。
例えばデータが「1」なら「1:」のように表示される。

echo $row['id'], ':';
$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8',
    'staff', 'password');
foreach ($pdo->query('select * from product') as $row) {
    echo "<p>$row[id]:$row[name]:$row[price]</p>";

同様に行からname列を取り出し、「:」を付けて表示する。
例えば「松の実」ならば「松の実:」のように表示される。

echo $row['name'], ':';

最後に行からprice列を取り出して表示する。
例えば「700」のように表示する。

echo $row['price'];

以上の処理によって
「1:松の実:700」
のように各行を表示する。

foreachループで繰り返すことで、最後の行までのデータを表示することができる。

指定した列のデータを取り出す(3通りの書き方)

test31-input.php
<?php require_once 'header.php';?>
<!-- <form action="test31.php" method="post"> -->
<!-- <form action="test31-output.php" method="post"> -->
<form action="test31-output2.php" method="post">
    <input type="text" name="keyword"> <input type="submit" value="検索">
</form>
<?php require_once 'footer.php';?>
方法①test31.php
$pdo = new PDO('mysql:host=localhost;dbname=takahashi1;charset=utf8', 'takahashi', 'takahashi');
$stmt =$pdo->prepare('select * from words where word=?');
$stmt->execute(array($_POST['keyword']));
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    echo $row['sense'];
}
方法②test31-output.php
$pdo = new PDO('mysql:host=localhost;dbname=takahashi1;charset=utf8', 'takahashi', 'takahashi');
$stmt = $pdo->prepare('select * from words where word=?');
$stmt->execute(array($_POST['keyword']));
foreach($stmt->fetchAll() as $row2){
    echo $row2['sense'];
}
方法③test31-output2.php
$pdo = new PDO('mysql:host=localhost;dbname=takahashi1;charset=utf8','takahashi','takahashi');
$stmt = $pdo->prepare('select * from words where word=?');
$stmt->execute(array($_POST['keyword']));
foreach ($stmt as $row){
\\  var_dump($stmt);
    echo $row['sense'];
}

20170317.png

201703172.png

fetchAllをfetchに置き換え

login-output.php置き換え前
 foreach ( $stmt->fetchAll() as $row ) {
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}
これでもいい
foreach ( $stmt as $row ) {
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );

1行ずつ、連想配列形式で取り出すことを指示し、返り値を $result に代入する

login-output.php置き換え後
while ( $row = $stmt->fetch ( PDO::FETCH_ASSOC ) ) {
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}
login-output.php
<?php require 'header.php'; ?>
<?php require 'menu.php'; ?>
<?php
session_start ();
// unset→指定した変数を破棄する
unset ( $_SESSION ['customer'] );
$pdo = new PDO ( 'mysql:host=localhost;dbname=takahashi1;charset=utf8', 'takahashi', 'takahashi' );
$stmt = $pdo->prepare ( 'select * from customer where login=? and password=?' );
// var_dump($stmt);
$stmt->execute ( array (
        $_POST ['login'],
        $_POST ['password']
) );

// foreachは配列とオブジェクトをループして使うための構文
// 配列ではないが使いやすくするために特別にforeachの反復処理で使えるように作られている
// $rowという変数に入れる
// $rows = $stmt->fetchAll ();
// var_dump($rows)
// foreach ( $stmt->fetchAll() as $row ) {
while ( $row = $stmt->fetch ( PDO::FETCH_ASSOC ) ) {
    // foreach ( $rows as $row ) {
    // 連想配列$_SESSION['customer']にキーを指定して追加し、値として連想配列を代入
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}
if (isset ( $_SESSION ['customer'] )) {
    echo 'いらっしゃいませ、', $_SESSION ['customer'] ['name'], 'さん。';
} else {
    echo 'ログイン名またはパスワードが違います。';
}
?>
<?php require 'footer.php'; ?>

■解説■

while ( $row = $stmt->fetch ( PDO::FETCH_ASSOC ) ) {
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}

1行ずつfetchして$rowに設定して、$rowの中身をループの中で毎回処理して、
中身が無くなったらfetchの返り値がfalseになってループを抜ける感じ。
while(条件式)→カッコ内の条件式がTRUEの間繰り返される。


わからないことばメモ

PDOStatementって何?

プリペアドステートメントを表す。
ステートメント実行時は関連する結果セットを表す

プリペアドステートメントって何?

SQLを使う際に、その条件とか値が異なるばあい、
それをパラメータ化して色んな値や条件で使いまわしできるもの。

参考サイト

PDOクラス

2017030801.png

PDOStatementクラス

2017030902.png

■prepareメソッドが返したPDOStatementインスタンスを見たいのでvar_dumpしてみた

$pdo = new PDO ( 'mysql:host=localhost;dbname=takahashi1;charset=utf8', 'takahashi', 'takahashi' );
$stmt = $pdo->prepare ( 'select * from customer where login=? and password=?' );
var_dump($stmt);
$stmt->execute ( array (
        $_POST ['login'],
        $_POST ['password']
) );

// foreachは配列とオブジェクトをループして使うための構文
// 配列ではないが使いやすくするために特別にforeachの反復処理で使えるように作られている
// $rowという変数に入れる
$rows = $stmt->fetchAll ();
var_dump($rows)
■実行結果
object(PDOStatement)#2 (1) { ["queryString"]=> string(51) "select * from customer where login=? and password=?" } array(0) { }

queryString

PDOStatementのプロパティ

この中の
$pdo = new PDO('mysql:host=localhost;dbname=takahashi1;charset=utf8','takahashi','takahashi');
$stmt = $pdo->prepare('select * from words where word=?');
$stmt->execute(array($_POST['keyword']));
foreach ($stmt as $row){
    echo $row['sense'];
}
queryStringにこれが格納されている
select * from words where word=?

PDOExceptionクラス

20170322.png

Exception::getMessage

例外メッセージを返す

fetch

▪️PDOStatement::fetch([int フェッチモード = PDO::FETCH_BOTH])
フェッチモード
フェッチモードとは結果セットから取り出したデータをどのような形式の変数に格納するかを表すパラメータ

定数 取得の形式 値の取得(例)
PDO::FETCH_ASSOC 連想配列 $row['name']
PDO::FETCH_NUM 一般配列 $row[0]
PDO::FETCH_BOTH 一般配列/連想配列 $row[0]/$row['name']
PDO::FETCH_OBJ オブジェクト $row->name
foreach(PDOの変数->fetchAll() as 結果を代入する変数) SQL文をexecuteメソッドで実行した結果を取得する
fetch() 1件データを取得。結果セットから次の行を取得する。
fetchAll() 結果データを全件まとめて配列で取得

PDO::FETCH_ASSOC

PDO::FETCH_ASSOC 結果セットに返された際のカラム名で添字を付けた配列を返す
連想配列
値の取得(例)→$row['name']

20170315.png
参考サイト
カラム.png

// foreach ( $stmt->fetchAll() as $row ) {
while ( $row = $stmt->fetch ( PDO::FETCH_ASSOC ) ) {
    $_SESSION ['customer'] = array (
            // idというキーで$row['id']を入れる
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}
if (

20170316.png

$rowにfetchで取れたid name address login passwordなどの中身が代入されて、
$rowの中身がある限りの間繰り返すということ。

結果セット

結果セットとはpng.png

結果セット.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away