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

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

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

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

PHP

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

XAMPP

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

Q&A

解決済

4回答

841閲覧

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

rikuta930

総合スコア18

mysqli

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

PHP

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

XAMPP

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

0グッド

2クリップ

投稿2019/05/16 03:21

編集2019/05/16 04:45

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

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

PHP

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

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

その後、

php

1 2 if($check_login_query == 1) { 3 $row = mysqli_fetch_array($check_database_query); 4 $username = $row['username']; 5 6 $_SESSION['username'] = $username; 7 header("Location: index.php"); 8 exit(); 9 10 }

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

php

1 2$row = array( 3 "email" => "test@gmail.com", 4 "password" => "**********" 5 ); 6

その後、

php

1$username = $row['username'];

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

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

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

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

php

1<?php 2 if (isset($_POST['login_button'])) { 3 $email = filter_var($_POST['log_email'], FILTER_SANITIZE_EMAIL); //emailをサニタイズ(特別な状態を打ち消す) 4 5 $_SESSION['log_email'] = $email; //session変数にemailを保存 6 $password = md5($_POST['log_password']); //パスワードを取得 7 8 $check_database_query = mysqli($con, "SELECT * FROM users WHERE email = '$email' AND password = '$password'"); 9 $check_login_query = mysqli_num_rows($check_database_query); 10 11 if($check_login_query == 1) { 12 $row = mysqli_fetch_array($check_database_query); 13 $username = $row['username']; 14 15 $_SESSION['username'] = $username; 16 header("Location: index.php"); 17 exit(); 18 19 } 20 21 } 22?>

var_dump($row);した結果

php

1array(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) "," }

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

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

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

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

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

rikuta930

2019/05/16 04:02

編集しました!質問不備の訂正依頼ありがとうございます。
m.ts10806

2019/05/16 05:10 編集

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

回答4

0

オフトピですが、普通に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/16 04:10

編集2019/05/16 04:19
ockeghem

総合スコア11701

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

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

rikuta930

2019/05/20 19:45

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

0

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

  • ご利用のツールは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 03:34

yambejp

総合スコア114837

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

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

rikuta930

2019/05/16 04:03

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

0

ベストアンサー

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

mysqli_num_rows

既に回答があるようにコードの質は決して良いとは言えません。
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 03:52

編集2019/05/16 04:09
m.ts10806

総合スコア80850

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

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

rikuta930

2019/05/16 04:03

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

2019/05/16 04:10

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

2019/05/16 04:25

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

2019/05/16 04:28

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

2019/05/16 04:29

>var_dump($row)はどこに足せばいいでしょうか? まず入れてみては。適切な場所に設置されなければエラーが出るだけです。
rikuta930

2019/05/20 19:48

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

0

ただの感想です

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

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

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

php

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

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

php

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

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

php

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

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

php

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

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

php

1if($check_login_query == 1) {

強い意志を感じるw

php

1$_SESSION['username'] = $username;

投稿2019/05/16 04:18

編集2019/05/16 21:45
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2019/05/16 04:19

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

退会済みユーザー

2019/05/16 21:41

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

2019/05/20 19:45

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

退会済みユーザー

2019/05/22 10:02

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

2019/06/11 17:44 編集

まだ、終了していないのでわかりませんが、後にセキュリティーに関する講義が控えているのかもしれませんね。教材によっては、初心者向けということもあり、セキュリティー云々よりも先に、まずは動くものを作るスキルを育むものもあるのではないでしょうか?te2jiさんの感想は、間違っていないと思いますが、アンチパターンも含めて、どうして使うべきではないのか学ぶいい機会だと思って、とりあえずは続けてみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問