はじめに
初めまして!恥ずかしながらこれが初投稿です。
自分はまだ学生なので、汚いコードや至らない点がありましたら申し訳ありません!
よろしくお願いいたします
##基本となるDBとSQL文
以下のDBがあったとします
MySQLで私が初めてログイン機能を初めて作った時のDBです
(passのとこは気にしないでください)
DB名: Login
テーブル名: user
id | name | pass | |
---|---|---|---|
1 | オヌマ | aaa@xxxmail.com | ???? |
2 | タケル | bbb@xxxmail.com | ???? |
3 | 田中 | ccc@xxxmail.com | ???? |
これに対するSQL文をphpで書いていきます
まずはDBに接続するためのPDOからです。
<?php
try {
//
$dsn = "mysql:dbname=Login;host=localhost;charset=utf8mb4";
$option = [
// 静的プレースホルダを指定
PDO::ATTR_EMULATE_PREPARES => false,
// 複文実行を禁止
PDO::MYSQL_ATTR_MULTI_STATEMENTS => false,
];
//
//dbhとはデータベース ハンドルの略
$dbh = new PDO($dsn, 'root', '', $option);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
次に、これを使って操作するSQL文を書いていきたいと思います
<?php
// セッション開始
session_start();
//pdoを読み込む
require('pdo.php');
$sql = ("ここに処理をしたいSQL文");
// SQL実行
$res = $dbh->prepare($sql);
$res->execute();
//または
$res = $dbh->query($sql);
//queryのためexecuteは要らない
同じSQL実行なのに
prepare()とquery()とは何ぞや!!!
と思う方は下の折り畳み記事に書きます
↓
prepare()とquery()の違い
prepare()は
SQL文の中に、ユーザーからの入力された「変動値」が入る場合に使用してから、SQL文を実行(execute)しなければならない
ん?もっとわかりやすく...??
主にSQLインジェクション攻撃対策の有無です
例を出すと
SELECT * FROM user WHERE name = (ユーザーの入力データ)
というSQL文に悪意のあるユーザーが
'';exit;
なんてデータが届き、そのまま実行されてしまってはexit(プログラムの終了コマンド)が実行されてしまう・・・
その他、悪意あるユーザーが他のSQL文を送ったり、
他のプログラムを実行させないようにプレースホルダという
ユーザーからの変動値が「ただの文字列(数値)として」 プログラムを実行させようということです。
##検索と出力
//nameが田中さんを探すSQL文
$sql =("SELECT * FROM user WHERE name = '田中'")
//変数の中に'田中'がある場合
$tanaka = "田中"
$sql2 =("SELECT * FROM user WHERE name ='" . $tanaka . "'");
// SQL実行
$res = $dbh->query($sql);
//配列の取得(SQL文に該当するデータを全取得)
$result = $res->fetchAll();
if ([] === $result) {
//該当なしの場合の出力処理
echo "そんな名前の人はいません!";
} else if (false === $result) {
//エラー時の処理
echo "SQLエラー";
}else {
//IDと名前の出力
for($j=0;$j<count($result);$j++){
echo "あなたのID:".htmlspecialchars($result[$j][1])."\n";
echo "あなたの名前:".htmlspecialchars($result[$j][2])."\n";
}
}
$resは正常にアクセスできたかを示すキーであり、実データではありません!!
なのでもし該当するデータがなくても$resはFALSEにはなりません
falseを返すのはSQL文が不正である可能性が高いです
##データの新規追加(POSTからの入力)
// 準備された文(プリペアードステートメント)を作成する
$sql = 'INSERT INTO user SET name=:name, mail=:mail, pass=:pass ;';
$res = $dbh->prepare($sql);
// プレースホルダ(SQLインジェクション対策)に値をバインドする
// INSERT文の[:name :mail :pass]の中にPOSTで拾った値を入力する
$res->bindValue(':name', $_POST['name']);
$res->bindValue(':mail', $_POST['mail']);
$res->bindValue(':pass', password_hash($_POST['pass'], PASSWORD_DEFAULT));
// SQLを実行
$r = $res->execute();
if (false === $r) {
echo "DBミス";
exit;
}
POSTでデータが送られてくることが前提のコードなので単体では動きませんよ?
passだけハッシュ化されてます。
password_verify('比較対象', 'DB内にあるハッシュ値')
password_hashはハッシュ化させたら元に戻すことは出来ませんので、上のコードで比較して同じものか確認できます
もし比較対象がハッシュ化前と同じ文字列ならTrueを返してくるはずです
##データの更新
基本的な部分はデータの新規追加と同じなのでSQL文のみ記述します
$sql = ("UPDATE `user` SET name=:name, mail=:mail, pass=:pass WHERE id = '更新させたいデータのID'");
//基本の構成
//INSERT
INSERT テーブル名 SET (追加させるフィールド名 = 追加する値)
//UPDATE
UPDATE テーブル名 SET (更新させるフィールド名 = 追加する値)WHERE (どのレコードが更新対象かの指定)
新規追加と違って更新は追加したいデータを入力した後に、WHEREで「どのデータを更新するか?」を指定しておかないといけません!!
エラーが出ないから大丈夫と思って実行すると、テーブル内の全データが更新され、内容が同じになります!
分かりにくかったらすいません・・・
##削除
$sql = ("DELETE FROM `user` SET WHERE name = '田中'");
//基本構成
DELETE FROM テーブル名 WHERE (削除したいレコードの条件を指定)
これで田中のレコードが削除できます
##最後に
この記事は私自身のために作ったものですが、他の方の役になるなら嬉しいです。
次からはもっとわかりやすく書きますので、よろしくお願いいたします。
あと、「この表現であってるよね」といろんなことを調べてこうやって記事にすることが意外と勉強になると感じたので、更新は遅いですが必ず更新したいです!!