忍者ブログ

からすまる日誌 mySQL

授業ノートのまとめ

高度(28) class(6)

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

高度(28) class(6)

編集のシーンで入力漏れがないかバリデーションをする

新規登録でもしたい
→関数化すれば使いまわせる
名前と値段は必須というやつ
 
優先順位としては、送信していいかどうかよりも前
 
e.preventDefault();の綴りを2回間違ってるので
Defaultの綴りに注意
 
こういう分岐

未入力がある?
はい→alert表示、プリベントデフォルト
いいえ→
 本当に編集していい?
 はい→実行
 いいえ→プリベントデフォルト
 
こういう感じ
 

ここまで

lunch.js
 
$(function(){
 //console.log("hoge");
 
 //バリデーション
 function check(){
  var chk;
  if($('#menu').val()  ==  ''  ||  $('#price').val()==''){//空なら
   chk = false;
  }else{
   chk=true;
  }
  return chk;
 }
 
 //編集ボタン
 $('#sub1').on('click',function(e){
  var chk=check();//上で宣言したのを実行
 
  //バリデーション
  if(!chk){
 
   //未入力項目あり
   alert('未入力項目あるよ');
   e.preventDefault();//イベント無効化
   
  }else{
 
   //入力OK,編集していいかどうか確認
   var  flag=confirm('編集してよろしいかな');
   if(!flag){//いいえを押された
    e.preventDefault();
   }
  }
 });
 
 //削除ボタン
 $('#sub2').on('click',function(e){
  var  flag=confirm('削除してよろしいかな');
  if(!flag){//いいえを押された
   e.preventDefault();
  }
 });
 
});
 

さて新規と、編集削除の分岐をする

form.phpに戻って、
 
</table>
    
    <?php if(empty($id)): ?>
    <p>
     <input type="submit" name="sub3" id="sub3" value="新規作成">
    </p>
    
    <?php else: ?>
    <p>
     <input type="submit" name="sub1" id="sub1" value="編集">
     <input type="submit" name="sub2" id="sub2" value="削除">
    </p>
    
    <?php endif  ?>
 

id="sub3"を付け加えたので
jsにも付け加え
 
 //新規作成ボタン
 $('#sub3').on('click',function(e){
  var chk=check();
  if(!chk){
   alert('未入力項目あるよ');
   e.preventDefault();
  }else{
   var flag=confirm('登録してよろしいかな');
   if(!flag){
    e.preventDefault();
   }
  }
 });
 

外部からのアタックにチケットの発行は有効なので、
ランダムな数をつくってhiddenでこっそりわたして
sessionととんできたのと比較する

自分で予定しているフォームからきていることを確認する
チケットの半券システム
 
echo time();
1900年だかから何秒経過したか
時間だけだとアタックしやすいので、
 
$ran = rand(1,100);
$salt="hogemakino";
$ticket =md5($ran.time().$salt);
echo $ticket ;
 

ソルトが大事
time()だけではアタックされるしrandomだけでも弱い
 


検証で確認すること
 

<input type="submit" name="sub" id="sub3" value="新規作成">
新規、編集、削除3つのボタンのnameを全部subに変える
 
すべて整っている前提で、
 
switch文で分岐をする
caseごとにbreakを忘れずに
 

ここまで

exec.php
 
<?php
 print_r($_POST);
 session_start();
 
 if($_SESSION["ticket"] != $_POST["ticket"]){//チケットの半券一致せず
  exit();
 }
 
 require_once("class/lunch.class.php");
 $obj = new Lunch();

 switch($_POST["sub"]){
  case "新規作成"://飛んできたvalueが新規
   $obj->setMenu($_POST["menu"], $_POST["price"], $_POST["c_id"]);
   break;
 
  case "編集":
   $obj->updateMenu($_POST["menu"], $_POST["price"], $_POST["c_id"], $_POST["id"]);
   break;
 
  case "削除":
   $obj->deleteMenu($_POST["id"]);
   break;
 }

//header("Location:list.php");
//exit();
 

?>


form.php
 
<?php
session_start();

$ran = rand(1,100);
$salt="hogemakino";
$ticket =md5($ran.time().$salt);
//echo $ticket ;
$_SESSION["ticket"] = $ticket;//sessionでチケット発行

//新規でも編集でもこのファイルを使いたい

require_once("class/lunch.class.php");
$obj = new Lunch();
 
if(!empty($_GET["id"])){
 //編集の場合
 
 //getで送られてくるidを事前につかまえる
 $id=intval($_GET["id"]);
 $title="編集";//タイトルも分岐によって変わる
 
 $arr = $obj->getMenuById($id);
 $menu = htmlspecialchars($arr["menu"],ENT_QUOTES);
 $price = $arr["price"];
 $c_id = $arr["c_id"];
 
}else{
 //新規作成の場合
 $title="新規作成";
 $menu = "";
 $price ="";
 $c_id=0;//A.I.(オートインクリメント)は1から始まる。わざとありえない番号を初期値にしておく
}


?>

<!DOCTYPE html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
  <title>メニュー<?php echo $title; ?></title>
  <link rel="stylesheet" href="css/style.css">
  <script src="../jquery-3.4.1.min.js"></script>
 </head>
 <body>
  <div id="container">
   <h1>メニュー<?php echo $title; ?></h1>
   
   <form action="exec.php" method="post">
    <table>
     <tr>
      <th><label for="menu">メニュー</label></th>
      <td><input type="text" name="menu" id="menu" value="<?php echo $menu; ?>"></td>
     </tr>
     
     <tr>
      <th><label for="price">価格</label></th>
      <td><input type="text" name="price" id="price" value="<?php echo $price; ?>"></td>
     </tr>
     
     <tr>
      <th><label for="c_id">カテゴリ</label></th>
      <td>
       <?php $obj->makeCatSelect($c_id); ?>
      </td>
     </tr>

    </table>
    
    <?php if(empty($id)): ?>
    <p>
     <input type="submit" name="sub" id="sub3" value="新規作成">
    </p>
    
    <?php else: ?>
    <p>
     <input type="submit" name="sub" id="sub1" value="編集">
     <input type="submit" name="sub" id="sub2" value="削除">
     <input type="hidden" name="id" value="<?php echo $id; ?>">
    </p>
    
    <?php endif ?>
    
    <input type="hidden" name="ticket" value="<?php echo $ticket;/*form側でもチケット発行*/ ?>">
    
   </form>
   
 
  <script src="js/lunch.js"></script>  
 </body>
</html>


lunch.js
 
$(function(){
 //console.log("hoge");
 
 //バリデーション
 function check(){
  var chk;
  if($('#menu').val() == '' || $('#price').val()==''){//空なら
   chk = false;
  }else{
   chk=true;
  }
  return chk;
 }
 
 //編集ボタン
 $('#sub1').on('click',function(e){
  var chk=check();//上で宣言したのを実行
 
  //バリデーション
  if(!chk){
 
   //未入力項目あり
   alert('未入力項目あるよ');
   e.preventDefault();//イベント無効化
   
  }else{
 
   //入力OK,編集していいかどうか確認
   var flag=confirm('編集してよろしいかな');
   if(!flag){//いいえを押された
    e.preventDefault();
   }
  }
 });
 
 //削除ボタン
 $('#sub2').on('click',function(e){
  var flag=confirm('削除してよろしいかな');
  if(!flag){//いいえを押された
   e.preventDefault();
  }
 });
 
 //新規作成ボタン
 $('#sub3').on('click',function(e){
  var chk=check();
  if(!chk){
   alert('未入力項目あるよ');
   e.preventDefault();
  }else{
   var flag=confirm('登録してよろしいかな');
   if(!flag){
    e.preventDefault();
   }
  }
 });
 
 
});


lunch.class.php
 
<?php
class Lunch{
 private $pdo;//外から直接アクセスはできないように
 
 public function __construct(){//コンストラクタ。初期化されたときに動く
  // -----------------
  //環境によって変更
  // -----------------
 
  $host="localhost";
  $dbuser="root";
  $dbpass="";
  $dbname="lunch";
  // -----------------
 
  $dsn = "mysql:host={$host}; dbname={$dbname}; charset=utf8";
  $this->pdo=new PDO($dsn,$dbuser,$dbpass); //$pdoとは書かない
 
 }//constructの終わり
 
 public function getAllMenu(){//publicでないと外から呼び出せない
  $sql = "SELECT * FROM foods";
  $rs = $this->pdo->query($sql);
  $rows = $rs->fetchAll(PDO::FETCH_ASSOC);
  return $rows;//戻り値
 }
 
 public function getMenubyId($id=1){//指定したid番号を取得、引き取るid番号が仮引数の$id
  $sql="SELECT * FROM foods WHERE id=:id";
  $stmt = $this->pdo->prepare($sql);
  $stmt->bindvalue(":id",$id,PDO::PARAM_INT);
  $stmt->execute();
  $row = $stmt->fetch(PDO::FETCH_ASSOC);
  return $row;
 }
 
 public function setMenu($menu,$price,$c_id){//idはオートインクリメントなので必要ない
  $sql = "INSERT INTO foods(menu,price,c_id) VALUES (:menu,:price,:c_id)";//メニューと値段とカテゴリidを追加
  $stmt = $this->pdo->prepare($sql);//クラス内の変数なのでstmtやsqlのスコープはここだけ
  $stmt->bindvalue(":menu",$menu,PDO::PARAM_STR);
  $stmt->bindvalue(":price",$price,PDO::PARAM_INT);
  $stmt->bindvalue(":c_id",$c_id,PDO::PARAM_INT);
  $stmt->execute();
  //戻り値は要らない
 }
 
 public function updateMenu($menu,$price,$c_id,$id){//どれがupdateされるか分からないので3つとも仮引数を用意
  //主キーである$idがないと全部書き換わってしまうのでどこのレコードか指定するため今回4つプロパティが要る
 
  $sql = "UPDATE foods SET menu=:menu, price=:price, c_id=:c_id WHERE id=:id";
  $stmt = $this->pdo->prepare($sql);
  $stmt->bindvalue(":menu",$menu,PDO::PARAM_STR);
  $stmt->bindvalue(":price",$price,PDO::PARAM_INT);
  $stmt->bindvalue(":c_id",$c_id,PDO::PARAM_INT);
  $stmt->bindvalue(":id",$id,PDO::PARAM_INT);//idも必要ですよ
  $stmt->execute();
 
 }
 
 public function deleteMenu($id){//パラメータは主キーであるidだけでいい
  $sql = "DELETE FROM foods WHERE id=:id";
  $stmt = $this->pdo->prepare($sql);
  $stmt->bindvalue(":id",$id,PDO::PARAM_INT);
  $stmt->execute();
 
 }
 
 //セレクトプルダウンに表示
 
 public function makeCatSelect($c_id){
  $sql = "SELECT * FROM cats";
  $rs = $this->pdo->query($sql);//レコードセットの中に結果セットを入れる形
 
  echo "<SELECT name=\"c_id\" id=\"c_id\">\n";
 
  //ダミーのオプション
  echo "<option value=\"\">以下から選択</option>\n";
 
  while($row = $rs->fetch(PDO::FETCH_ASSOC)){
 
   $selStr = $c_id==$row["c_id"] ? " selected" : "";//三項演算。selectedか何もないか。あるにせよないにせよechoする。一致すればselected、なければ""
 
   //option value="1"うどん</option>みたいなのを出力したい
   echo "<option value=\"{$row["c_id"]}\"{$selStr}>";
   echo htmlspecialchars($row["cat"],ENT_QUOTES);
   echo "</option>\n";
  }
  echo "</select>\n";
 }
 
}
?>


style.css
 
body{
 background:#eff;
}
#container{
 width:80%;
 margin:auto;
}
table{
 border-collapse:collapse;
}
th,td{
 padding:0.3rem 0.5rem;
 text-align:left;
 background:#fff;
 border:solid 1px #555;
}
th{
 background:#ccc;
}



なおエラーがでたが原因は、

switch($_POST["sub"]){
  case "新規作成"://飛んできたvalueが新規
   $obj->setMenu($_POST["menu"], $_POST["$price"], $_POST["$c_id"]);
   break;
 
$_POST["$price"]じゃなくて、
$_POST["price"]
 
$がいらなかった
  
PR

コメント

ただいまコメントを受けつけておりません。

プロフィール

HN:
karasumaru
性別:
非公開

P R