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

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

ただいまの
回答率

90.51%

  • PHP

    24035questions

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

  • XAMPP

    620questions

    XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

  • mysqli

    178questions

    MySQLiはPHP5より導入されているデータベース用のドライバです。MySQL 4.1.3以降の新しい機能の利点をまとめています。

なぜSQLの列を取得して、配列に入れる必要があるのか?

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,193

rikuta930

score 5

phpでツイッターのクローンをUdemyの教材を見ながら作成しています。

教材でどうしても意味の分からない部分があったので、教えていただきたいです。

$check_database_query = mysqli($con, "SELECT * FROM users WHERE email = '$email' AND password = '$password'");
$check_login_query = mysqli_num_rows($check_database_query);

SQLのテーブルに入っているユーザー情報を取り出して、変数に入れて、行数がいくつかを変数に格納していました。
ここで一つ目の質問なのですが、mysqli_num_rowsは「結果の行数を取得する」という意味とマニュアルに書いてあったのですが、これは「変数の情報と適応する情報が入った列が何行あるのか?」を取得するという認識で正しいのでしょうか?

その後、

        if($check_login_query == 1) {
            $row = mysqli_fetch_array($check_database_query);
            $username = $row['username'];

            $_SESSION['username'] = $username;
            header("Location: index.php");
            exit();

        }

まず、If文で、先ほど得た行数が1、つまり、正常に情報がテーブルに入っているかどうかを確認しています。
次に、mysqli_fetch_array関数を使って、結果の行を連想配列で取得しています。
ここで二つめの質問なのですが、ここで取得した連想配列とは、下のようなものでしょうか?

$row = array(
    "email"    =>    "test@gmail.com",
    "password" =>    "**********"
    );


その後、

$username = $row['username'];


と続くのですが、$row['username']というのはどのような意味なのでしょうか?
予想では、ユーザーネームに入っている配列の「username」キーの情報を変数に格納するという意味だと思うのですが・・・・

最後の質問なのですが、exit();は必要なのでしょうか?

わかる方いらっしゃいましたら、教えて下さい!!

わからない部分は $check_login_query からです

<?php
    if (isset($_POST['login_button'])) {
        $email = filter_var($_POST['log_email'], FILTER_SANITIZE_EMAIL); //emailをサニタイズ(特別な状態を打ち消す)

        $_SESSION['log_email'] = $email; //session変数にemailを保存
        $password = md5($_POST['log_password']); //パスワードを取得

        $check_database_query = mysqli($con, "SELECT * FROM users WHERE email = '$email' AND password = '$password'");
        $check_login_query = mysqli_num_rows($check_database_query);

        if($check_login_query == 1) {
            $row = mysqli_fetch_array($check_database_query);
            $username = $row['username'];

            $_SESSION['username'] = $username;
            header("Location: index.php");
            exit();

        }

    }
?>

var_dump($row);した結果

array(24) { [0]=> string(1) "3" ["id"]=> string(1) "3" [1]=> string(8) "Chandler" ["first_name"]=> string(8) "Chandler" [2]=> string(4) "Bing" ["last_name"]=> string(4) "Bing" [3]=> string(13) "chandler_bing" ["username"]=> string(13) "chandler_bing" [4]=> string(18) "Chandler@gmail.com" ["email"]=> string(18) "Chandler@gmail.com" [5]=> string(32) "e04857f0b448a8d84176da365bca0da6" ["password"]=> string(32) "e04857f0b448a8d84176da365bca0da6" [6]=> string(10) "2019-05-15" ["signup_date"]=> string(10) "2019-05-15" [7]=> string(54) "assets/images/profile_pics/defaults/head_deep_blue.png" ["profile_pic"]=> string(54) "assets/images/profile_pics/defaults/head_deep_blue.png" [8]=> string(1) "0" ["num_posts"]=> string(1) "0" [9]=> string(1) "0" ["num_likes"]=> string(1) "0" [10]=> string(2) "no" ["user_closed"]=> string(2) "no" [11]=> string(1) "," ["friend_array"]=> string(1) "," }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • ockeghem

    2019/05/16 13:58 編集

    教材はこれですか?…どうも違うようです(修正)
    https://www.udemy.com/php7basic/

    キャンセル

  • mts10806

    2019/05/16 14:08

    解決されたようですが、どのように理解し、解決とされたかコメントいただけると幸いです。
    https://teratail.com/help/question-tips#questionTips4-2

    キャンセル

  • mts10806

    2019/05/16 14:09 編集

    >ockeghemさん
    CMはよく見ますけどこの内容でこんなにお金取るんですね。
    自身がある程度仕事でやっているからこその感覚かもしれませんが、すごい商売・・・。

    キャンセル

回答 4

+2

なにを参照されたのかわかりませんが、あまり質が良くないソースです
ロジック以外あまり参考にされないほうがよさそうです
とりあえず

  • ご利用のツールはmysqliの手続き型処理を行っています
  • select文を実行して行数を数えて$check_login_queryに代入しています
  • $check_login_queryが1件つまりusersテーブルに指定のメールアドレスとパスワードの組み合わせが1件だけあるときという条件
  • 1レコード取り出してuserテーブルのusernameカラムを参照しています
  • 「$_SESSION['username'] = username;」はおそらくtypo、変数名に$が抜けています。
  • セッションにusernameを保持してtopページに飛びます
  • topページにおそらくusernameが指定されていればログイン状態だというライブラリが読まれているのでしょう

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/16 13:03

    とても分かりやすい回答ありがとうございます。

    キャンセル

+2

オフトピですが、普通にSQLインジェクション脆弱性がありますね。yambejpさんが指摘されているように質が良くないソースなので、教材を変えた方がよいでしょう。
おそらく、以下の行で対策しているつもりなのでしょうが…

$email = filter_var($_POST['log_email'], FILTER_SANITIZE_EMAIL); //emailをサニタイズ(特別な状態を打ち消す)

FILTER_SANITIZE_EMAILは以下の意味ですので…

英字、数字および !#$%&'*+-=?^_`{|}~@.[] 以外のすべての文字を取り除きます。 https://www.php.net/manual/ja/filter.filters.sanitize.php

英字、数字および !#$%&'*+-=?^_`{|}~@.[] だけを使えば攻撃ができます。特に問題なのは、シングルクォート「'」が許可される点です。

例えば、以下をメールアドレスとして指定すると攻撃ができます。

'OR`username`='ockeghem'OR'0

生成されるSQL文は下記となり、パスワードがわからなくても、ユーザー名 ockeghem でログインできます。(パスワードは一応入っていますが、結果に依存しません)

SELECT * FROM users WHERE email = ''OR`username`='ockeghem'OR'0' AND password = 'd41d8cd98f00b204e9800998ecf8427e'

上記のSQL文に空白、改行や括弧を補って見やすくすると以下のようになります。

SELECT * FROM users WHERE email = '' OR
        `username`='ockeghem' OR
        ('0' AND password = 'd41d8cd98f00b204e9800998ecf8427e')

3項目のORになっていますが、これらのうち2行目(username='ockeghem')が username列がockeghemの行のみ TRUE になり他の項目は常に FALSE です。なので、ユーザ名ockeghemでログインできるというわけです。同様に、他のユーザー名でもログインできます。

(追記)
「セッションIDの固定化」という脆弱性もありますね。詳しくは「安全なウェブサイトの作り方」等で調べてください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/21 04:45

    なるほど。セキュリティーの観点をしっかりと考えることが大切なんですね。勉強になりました。

    キャンセル

checkベストアンサー

+1

PHPマニュアルを確認してください。
辞書がわりにでも使えるようになるとPHPの理解度がグッとあがります。

既に回答があるようにコードの質は決して良いとは言えません。
filter_var()が申し訳程度に使ってあるだけで結局$_POST使っているところとか。
SQLエスケープ使わずにSQL文に値を直接突っ込んでいるところとか
$_SESSION['username'] = username;なんてそもそも定義した変数$usernameじゃなくて定数になってますし。
書籍を転記したからミスったのかもしれないですが、質問として提示する前に動作させてみたほうが良いです。
$check_login_queryが1じゃなかったらどうなるんでしょう。何も出力しませんね。
DB接続失敗したら?SELECT文が正しく機能しなかったら?など考慮の漏れが著しいです。

古い書籍なのか、初心者向けなのか分からないですが、初心者でもあまり参考にしてほしくない書籍・コードだと個人的には思います。

追記を受けて

「変数の情報と適応する情報が入った列が何行あるのか?」を取得するという認識で正しいのでしょうか?

「変数の情報と」の意味が分からないですが、おおよそ理解通りかと。
PHPマニュアルにある「結果の行数」とは「今回の場合はSELECT文を実行した結果の行数」が入っていると考えて良いです。
select文の条件を色々変えてみたうえでmysqli_num_rows()の結果をechoで出力してみてどうなるか確認してみると良いです。

ここで二つめの質問なのですが、ここで取得した連想配列とは、下のようなものでしょうか?

データによるので取得結果をvar_dump()で確認してみては如何でしょうか。
「想定通りの情報が入っているか」デバッグにもなるのでぜひ確認してみてください。

$row['username']というのはどのような意味なのでしょうか?
予想では、ユーザーネームに入っている配列の「username」キーの情報を変数に格納するという意味だと思うのですが・・・・

ここで「予想」してしまうとプログラミングの概念的におかしくなります。
プログラムは書いたとおりにしか動かないので実態を確認すべきです。
1つ前で結果をvar_dump()で確認すればこの疑問の理解が進み、解消できますね。

最後の質問なのですが、exit();は必要なのでしょうか?

はい。基本的には必要とは思います。
なぜならheaderはあくまでレスポンスを定義するものであり、リダイレクトを宣言したからといって、その時点で画面遷移が起こるわけではないからです。
試しにheader()の直後に何か処理(できればログ出力とか、セッションとかで画面遷移しても影響が確認できる処理)を記載してみると良いです。

exitを書くのはこれ以降は何も処理を行いませんという意味で「プログラムを終了させる」ためであると言っても良いです。
もちろん「お作法のように書いておこう」ということであり、exitを書かなくても済むようなプログラムが望ましいですけど、「必ず何もない前提」のようなプログラミングもよろしくありません。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/16 13:03

    そうなんですね。結構楽しく取り組んでいただけにショックですね・・・・。
    回答ありがとうございます。

    キャンセル

  • 2019/05/16 13:10

    なるほど!とても分かりやすいです。試してみます!

    キャンセル

  • 2019/05/16 13:25

    初歩的なことで恐縮なのですが、var_dump($row)はどこに足せばいいでしょうか?

    キャンセル

  • 2019/05/16 13:28

    あまり理解を得られた感がないのですが、プログラミングはtrial and errorで進めていくものだと思っていて、
    要は
    実際に書いて、動かして、調べて、また書いて、動かして…
    の繰り返しで身に付けていくものです。スポーツで例えると、野球で、本を読んだからってヒットを打てるようになるわけでもキャッチボールがうまくなるわけでもありません。
    理論を学ぶのは大事ですが実を結ぶのは結局のところ「やってみること」です。
    今回提示されたコードも「実行してみる」「固定の情報に手を加えてみる」「処理を削ってみる」「途中で値を出力してみる」などしてみることで得られるものは多く、単に書籍のコードとにらめっこしているだけではほとんど何も得られません。
    構文間違えばそれを間違っていると親切にエラーを出してくれます。自身のPCが壊れるなんてことはありません。
    マニュアルも整備されています。
    そこをフル活用できるようになると初心者からすぐに卒業することができると思います。

    キャンセル

  • 2019/05/16 13:29

    >var_dump($row)はどこに足せばいいでしょうか?

    まず入れてみては。適切な場所に設置されなければエラーが出るだけです。

    キャンセル

  • 2019/05/21 04:48

    ありがとうございます。
    入れてみました!連想配列についての理解が少し深まったと思います。
    これからも、引き続き色々試してみることは続けたいです。
    それから、もっとマニュアルをちゃんと活用しようと思います。

    キャンセル

-2

ただの感想です

反面教師的な資料なんですかねぇ。。。
後で問題点を上げていくようなやつなのであれば、そう書いて下さい。
ノイズでしかないです。
質問が頭に入ってきません。

追記
せっかくなんで、どんなノイズが発生するか書いてみます。

これだけで、他の箇所の isset 確認しなくていいって思うなよ!w

if (isset($_POST['login_button'])) {

SQL インジェクション通すための苦肉の策ね。
どうせなら、パスワードも SANITIZE 使って、複数パスワードでのログイン見せればいいのに。

$email = filter_var($_POST['log_email'], FILTER_SANITIZE_EMAIL);

後でパスワードの解析でもやらせるのかなぁ。

$password = md5($_POST['log_password']);

password 比較を外出しにしてないとか、準備万端だねぇ。
あぁ、md5 はここで生きるのかw

$check_database_query = mysqli($con, "SELECT * FROM users WHERE email = '$email' AND password = '$password'");

なんで==なんだろ。ここだけ意図が分からん。

if($check_login_query == 1) {

強い意志を感じるw

$_SESSION['username'] = $username;

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/16 13:19

    全部アンチパターンなんで、多分そういう資料なんだと思いますけど。。。

    キャンセル

  • 2019/05/17 06:41

    追記してみましたw
    session_regenerate_id と CSRF 対策もないから、そのへんもなんかやるのかもねぇ。

    キャンセル

  • 2019/05/21 04:45

    追記ありがとうございます。
    今回分かったことは、php初心者からすると、なにが悪いのかが分からず、良い教材を探す時に手間取るということでした。
    経験値上げていけば、いずれ解決するとは思いますが・・・・・、せっかくお金を払って買った教材なので、結構ショックですね・・・・・。
    おすすめの教材などはありますでしょうか?

    キャンセル

  • 2019/05/22 19:02

    追記に書いたように、後で「この辺に問題がありました!動くだけじゃダメなのよ!」って言うパターンのやつだと思ったんだけど、違ったってことですかね?
    「わざとらしい脆弱にするための仕掛け」がいくつも含まれているんですけど。

    キャンセル

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

  • PHP

    24035questions

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

  • XAMPP

    620questions

    XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

  • mysqli

    178questions

    MySQLiはPHP5より導入されているデータベース用のドライバです。MySQL 4.1.3以降の新しい機能の利点をまとめています。