わかるようでわからない PHPのFETCHを解説!

わかっているようでわからない、PHPのFETCHを解説!

PHP わかるようでわからない PHPのFETCHを解説!

こんにちは、takaです。

 

PHPでデータベースを操作するときに「fetch(PDO::FETCH_ASSOC)」みたいなコード、たまに出てきますね?

・・・正直、何をしてるか分からなくないですか?

僕は「『fetch』って日本語でいうと「〜を取ってくる」って意味だから、何かデータを取ってきているんだな」ぐらいの理解でいましたが、この「fetch」がわかるとデータベースの理解がぐっと深まります。

 

今回はこの初心者にとっていまいち分かりにくいPHPにおける「fetch」について説明していきたいと思います。

また、様々な種類がある「fetch」をどのように使い分けるのかも、実装したい機能から考える、ということから具体的にみていきます。

 

この記事を読むことで、よく分からずに使っていた「fetch」をしっかりと理解することが出来ますよ。

まずは構造を知る。

冒頭で紹介した「fetch(PDO::FETCH_ASSOC)」ですが、これは大きく2つのカテゴリーに分けることができます。

 

fetch・・・前半のこの部分は「どのようにデータを取ってきますか?」というデータの取り方を表す部分。

(PDO::FETCH_ASSOC)・・・後半のこの部分は「取ってきたデータをどのような形で格納しますか?」という部分。

 

なので、この前半部分と後半部分に「どんな種類があって、どんな働きがあるのか」ということを抑えておけば、「fetch」関連のことは大方わかるということになります。

まずは前半部分である「どのようにデータを取ってくるのか?」を見ていきましょう。

 

データの取り方は主に4種類。でもよく使うのは2つ。

データを取ってくる方法は主に次の4つです。

*()にあるのは、公式のリンクとなっています。

 

・fetch・・・該当するデータを1行返す。(fetch)

・fetchAll・・・該当するすべてのデータを配列で返す。(fetchAll)

・fetchColumn・・・該当するデータから単一のカラムを返す。(fetchColumn)

・fetchObject・・・該当するデータを1行取得して、それをオブジェクトとして返す。(fetchObject)

 

このうち、よく使用されるのは「fetch」と「fetchAll」です。

実際にどのようにデータが取得されるのかは、あとで詳しく見ていきます。

 

次に後半部分の「データをどのように格納するのか?」をご紹介します。

 

データの格納の仕方

後半部分は「データの格納の仕方」。これはもともとPHP側で定義されている「定義済み定数」を用いて決定していきます。

以前、こちらの記事でも紹介した「$_POST」のように予めPHP側で「これ用意してるから、使っていいよ!」というやつです。

関連記事

こんにちは、takaです。   「$_POST」。 いきなり何だ、と思われるかもしれませんがこの変数しっかり分かってますか?   PHPを学習する上で非常に重要な概念ですが、初心者がつまずく最初のところではないでしょうか[…]

$_POST_comprehend

 

<定義済み定数の種類>

  • PDO::FETCH_ASSOC・・・結果セットに 返された際のカラム名で添字を付けた配列を返します。

  • PDO::FETCH_BOTH (デフォルト)・・・結果セットに返された際のカラム名と 0 で始まるカラム番号で添字を付けた配列を返します。

  • PDO::FETCH_NUM・・・結果セットに返された際の 0 から始まるカラム番号を添字とする配列を返します。

 


*上記で紹介した定数は「fetch」と「fetchAll」で使用できる定数となります。

またこれ以外にもまだまだ種類はたくさんありますが、今回はあえて3つに絞ってご紹介してます。

「他にも何があるのか気になる!」という方は、上記にある「データの取り方」でご紹介した公式のリンクにアクセスしていただき、「パラメーター」という部分をご参照ください。


 

これでfetchに関わる前半部分、後半部分の紹介が終わりました。

 

ここまで読んでみて、どうでしょう。

「ちっともイメージがわかない・・・」となっているのではないでしょうか。僕もこれだけ読んだときは、「で、結局どんな感じにデータは取得してるんですか?」と思いました。

 

次に見ていきたいのは、「fetch」と「fetchAll」をそれぞれ用いてデータの格納の仕方でご紹介した3つの定義済み定数を組み合わせることで、「どのようにデータが取得されるのか?」を詳しく見ていきます。

 

取得されるデータの中身を見ていこう!

まずはデータを引っ張ってくる元となるデータベースを用意します。

今回は下記のデータを用意しました。

php_fetch_masterdata

 

このデータを取得するために、コードは下記のように記述しています。

<?php

try {

  $dsn = 'mysql:dbname=php_sample01;host=localhost;charset=utf8';
  $user = 'root';
  $password = 'root';
  $options = array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
  );

  $dbh = new PDO($dsn, $user, $password, $options);

  $stmt = $dbh->prepare('SELECT * FROM users WHERE age >= 40');
  $stmt->execute();

  $result = $stmt->fetch(PDO::FETCH_ASSOC); 
  //ここにある「fetch」や()の定義済み定数を変えていくよ!

  print_r('<pre>');
  print_r($result);
  print_r('</pre>');
  
} catch (Exception $e) {
    error_log('障害が発生しており、ご迷惑をおかけしています。');
}

?>

○SQL文について

→SQL文で、(‘SELECT * FROM users WHERE age >= 40’)としているので、ここでは「データベースの中から40歳以上のデータを選ぶ」という命令を出している、ということになります。

○<pre></pre>について

→print_r($result)を<pre>というタグで囲っていますが、これは出力結果を見やすくするためにつけてます。つけなくても問題はありませんが、結果がかなり見づらいので今回はこのようにしてます。

 

*上記のコードを見て、「そもそもPDOとかってなんですか?」という方はこちら。

関連記事

こんにちはtakaです。   PHPを学習していく上で切っても切れない「データベース」との関係。 PDOやらtry~catchやら、最初に見た時は「何を言ってるの?」と感じた方、多いと思います。もちろん僕も。 今回の記事ではそんな[…]

php_database

 

fetchで取得されるデータをみてみよう

おさらい:fetch=該当するデータを1行返す

 

<fetch+FETCH_BOTH>

$result = $stmt->fetch(PDO::FETCH_BOTH); 

<結果>

fetch+fetch_both

なんでこのようなデータになるのかを見てみると・・・

fetch = 該当するデータ、ここだとage(年齢)が40歳以上のデータを1行返すので一番初めの「鈴木太郎」さんが該当する

FETCH_BOTH = 「カラム名」と「0から始まるカラム番号で添字をつけた」配列の形式でデータを格納する。

簡単にいうと、連想配列の形式と通常の配列の形式の2つの配列をデータに格納するということ。だから「BOTH(両方)」という名前になっている。

 

<fetch+FETCH_ASSOC>

$result = $stmt->fetch(PDO::FETCH_ASSOC); 

<結果>

fetch+fetch_assoc

fetch = 該当するデータを1行返す

FETCH_ASSOC = カラム名を添字にした配列形式(連想配列)でデータを格納する。

 

<fetch+FETCH_NUM>

$result = $stmt->fetch(PDO::FETCH_NUM); 

<結果>

fetch+fetch_num

fetch = 該当するデータを1行返す

FETCH_NUM = 0から始まるカラム番号を添字としてデータを格納する。

 

と見てきたように、「fetch」は1行しかデータを取ってこない+配列の形式でデータが格納される、という形です。

今回のSQL文である「40歳以上のデータを取ってくる」だと、鈴木太郎さん以外にも高橋綾さんと橋下譲さんも該当しますが、あくまでfetchは「1行しか取ってこない」ので、結果は上記のようになります。

 

次に「fetchAll」を見てみましょう。

 

fetchAllで取得されるデータをみていこう

おさらい:fetchAll=該当するすべてのデータを配列の形式で返す

*どんな感じでデータが取得されるのか、これまでのことを参考にして考えてみてください。

 

 

 

 

<fetchAll + FETCH_ASSOC>

$result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

fetchAll+fetch_assoc

fetchAll = 該当するすべてのデータを配列の形式で返す

FETCH_ASSOC = カラム名を添字にした配列形式(連想配列)でデータを格納する。

 

さて今度は40歳以上の全ての方のデータを取得することが出来ました。さっき出番がなかった高橋さんと橋下さんもデータに格納されていますね。

でも、1つ不思議な部分があります。よーくみると、Arrayの中にさらにArrayという形でデータが格納されています。

これは、上記の赤線にあるとおりfetchAllもFETCH_ASSOCもどちらも配列の形式でデータを扱うからです。

 

この形を「二次元配列」と呼びます。

初見だとびっくりするかもしれませんが、単に配列の中に配列が入っているだけでそれぞれ番号の添字(背番号的なもの)が振られて管理されているだけです。

[0]だったら鈴木さんのデータ、[1]だったら高橋さんのデータ、といった具合です。

 

<fetchAll+FETCH_NUM>

$result = $stmt->fetchAll(PDO::FETCH_NUM); 

<結果>

fetchAll+fetch_num

fetchAll = 該当するすべてのデータを配列の形式で返す

FETCH_NUM = 0から始まるカラム番号を添字としてデータを格納する。

 

カラム名だったところが数字に変わるだけ、でした。

 

*FETCH_BOTHはかなりみづらいので、上記2つの結果が足されたもの、としてお考えください。

 

実装したい機能から、使うべきfetchの組み合わせは決まる

ここまで、主に「fetch」と「fetchAll」を軸としてそれぞれのデータの格納の仕方を組み合わせて、実行結果を見てきました。

それで次に考えなくちゃいけないのは、「実際にコードを書くときは、どのように使い分ければいいのか?」ということだと思います。

 

この問いに対する答えは非常にシンプルです。

 

「実装したい機能によって、組み合わせを決める

 

です。

まあ、当たり前なんですが・・・。

 

具体的にどういうことかを簡単に紹介します。

 

ログイン機能を実装したいときに、どの組み合わせでfetchを使う?

例えば「ログイン機能」をウェブ上で実装したいな、となった場合。

大まかな処理の流れは次のようになるかと思います。

 

① ユーザーにメールアドレス+パスワードを入力してもらう

② そのパスワードがちゃんとアドレスの形式とパスワードの形式になっているかのチェック(バリデーションチェック)

③ ②がOKなら、メールアドレスを基にしてデータベース(DB)に登録されているパスワードのデータを引っ張ってくる

④ DBから引っ張ってきたパスワードと、ユーザーに入力してもらったパスワードが本当にあっているのかをチェックする

⑤ もしパスワードが一致したら、ログイン成功。

 

といった流れです。

ここで注目して欲しいのは③の処理の部分で、「メールアドレスを基にして、DBからパスワードのデータを引っ張ってくる」というところ。ここで今回学んだ「fetch」くんが活躍します。

 

さてここで問題。上記の処理をするためには、今回学んだ「fetch」の中でどのように組み合わせてデータを取ってくればいいのでしょうか。

 

 

 

 

 

 

 

答え

fetch(PDO::FETCH/ASSOC)

となります。

 

なので、実装したい機能の流れを洗い出すなかで「ここはDBからデータを取ってくる必要があるけど、この場合はfetch、この場合はfetchAll」といった具合で選択する、という感じです。

 

難しいことでも、きっとわかるようになる。

一番初めにfetch(PDO:FETCH_ASSOC)と見たときの衝撃は忘れません。

ちなみにそのときのこともブログに書いていますが、本当何もわかってません(笑)

関連記事

Webサービス部 Lesson10/ 2hour Sep / 2hour Total / 103.5 hour   目次 1 FETCH_ASSOCとは何か? FETCH[…]

DAY 38 WEBサービス部 Lesson10 FETCH_ASSOC

 

でも、学習を進めるにつれてこれが何を意味しているのか、調べながら徐々に理解することができました。

これからもこうしたことが沢山出てくるかと思います。

その都度挫折しそうになりますが、「まあそのうち学習が進めば理解できるだろう」という気持ちで取り組めば大方大丈夫です。

 

この記事で少しでもみなさんの「わからん!」が減ってくれると嬉しいです。

最後までありがとうございました。

 

ではまた!

わかるようでわからない PHPのFETCHを解説!
最新情報をチェックしよう!