ログイン機能

#処理フロー

セッション関連の設定
　　　↓　requireでfunctionファイル読み込む
ログイン状況の確認　
　　　↓　requireでauthファイル読み込む
post送信の確認
　　　↓　if post送信されたら
バリデーションチェック
　　　↓　if $err_msgに値が入っていなければ
DB接続

##HTML
- formのmethodをpostにしてsubmitから値を受け取るようにする
- nameに任意の名前を記述して$_POSTで使用できるようにする
- 新規登録とあまり変わらない


```index.php

<!DOCTYPE html>
<body>

    <div>
        <section>
            <form action="" method="post">
                <h2>ログイン</h2>
                <div class="area-msg">
                  <?php
                   if(!empty($err_msg['common'])) echo $err_msg['common'];
                  ?>
                </div>
                <label class="<?php if(!empty($err_msg['email'])) echo 'err'; ?>">
                  <input type="text" name="email" value="<?php 
        if(!empty($_POST['email'])) echo $_POST['email']; ?>">
                </label>
                <div class="are-msg">
                  <?php if(!empty($err_msg['email'])) echo $err_msg['email']; ?>
                </div>
                <label class="<?php if(!empty($err_msg['pass'])) echo 'err'; ?>">
                  <input type="text" name="pass" value="<?php 
        if(!empty($_POST['pass'])) echo $_POST['pass']; ?>">
                </label>
                <div class="are-msg">
                  <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?>
                </div>
                <label>
                  <input type="checkbox" name="pass_save" value="ログイン">
                </label>
                <div class="btn-container">
                  <input type="submit" class="" value="ログイン">
                </div>
                パスワードを忘れた方は<a href="passre.html">コチラ</a>
            </form>
        </section>
    </div>
    </body>
    </html> 
```
##function.php

- sessionの設定
- debugについては別記事でまとめる


```function.php
$debug_log = true;
 
    function debug($str){
       global $debug_flg;
     if(!empty($debug_flg)){
       error_log('デバッグ：'.$str);
     }
    }

    //=============================
    //セッション準備
    //=============================
    //セッショnファイルの置き場を変更する（/var/tmp/以下に置くと３０日は削除されない）
    session_save_path("/var/tmp/");
     //ガーベージコレクションが削除するセッションの有効期限を設定（30日以上経っているものにたいしてだけ１００ 
     分の１の確率で削除する）
    ini_set('session.gc_maxlifetime', 60*60*24*30);
    //ブラウザを閉じても削除されないようにクッキー自体の有効期限を伸ばす
    ini_set('session.cookie_lifetime', 60*60*24*30);
    //セッションを使う
    session_start();
    //現在のセッションIDを新しく生成したものと置き換える（なりすましのセキュリティ対策）
    session_regenerate_id();

     //================================
     //画面表示処理開始ログ吐き出し関数
     //================================
     function debugLogStart(){
       debug('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>画面表示処理開始');
       debug('セッションID：'.session_id());
       debug('セッション変数の中身：'.print_r($_SESSION,true));
       debug('現在日時タイムスタンプ：'.time());
       if(!empty($_SESSION['login_date']) && !empty($_SESSION['login_limit'])){
         debug('ログイン期限日時タイムスタンプ：'.( $_SESSION['login_date'] + 
       $_SESSION['login_limit'] ) );
      }
     }
```

##auth.php
- ログイン状況の確認
- ＄_SESSIONでログインしたことあるユーザーかの確認
- なけなければ後続処理
- あれば期限内か確認、期限内ならそのままログイン、期限外ならsession_destroyしてログイン画面へ遷移


```autu.php<?php

//============================
// ログイン認証　自動ログアウト
//============================
//ログインしている場合
if( !empty($_SESSION['login_date']) ){
  debug('ログイン済みユーザーです。');

  //現在日時が最終ログイン日時＋有効期限を超えていた場合
  if( ($_SESSION['login_date'] + $_SESSION['login_limit']) < time()){
    debug('ログイン有効期限オーバーです。');

    //セッション削除（ログアウトする）
    session_destroy();
    //ログインページへ
    header("Location:login.php");
  }else{
    debug('ログイン有効期限内です。');
    //最終ログイン日時を現在日時に更新
    $_SESSION['login_date'] = time();
    debug('マイページへ遷移します。');
    header("Location:mypage.html");//マイページへ
  }

}else{
  debug('未ログインユーザーです。');
}
 ?>
```

##バリデーション・DB接続

- post送信されていたらバリデーションチェック
- $err_msgが空ならtry,cathcでDB接続
- email照合→password,id取得→fetchで配列を取得→password_veryfyで＄_POST['password']とarray_shift($result)で先頭の配列とあっているか照合(今回ならSELECTでpasswordを先に取得している)
- 合っていれば＄_SESSIONに最終ログイン日時の更新、照合結果のidを入れ任意のファイルへ遷移、合っていなければエラーメッセージ
- ログイン保持（$pass_save）にチェックが入っていればリミットを３０日に、なければ１時間に

```login.php
if(!empty($_POST)){
    debug('post送信があります。');

    //変数にユーザー情報を代入
     $email = $_POST['email'];
     $pass = $_POST['pass'];
     $pass_save = (!empty($_POST['pass_save']))? true : false;

     //emailの形式チェック
     validEmail($email, 'email');
     //emailの最大文字数チェック
     validMaxLen($email, 'email');

     //パスワードの半角英数字チェック
     validHalf($pass, 'pass');
     //パスワードの最大文字数チェック
     validMaxLen($pass, 'pass');
     //パスワードの最小文字数チェック
     validMinLen($pass, 'pass');

     //未入力チェック
     validRequired($email, 'email');
     validRequired($pass, 'pass');

    if(empty($err_msg)){
      debug('バリデーションチェックOKです。');

      try{
        $dbh = dbConnect();
        $sql = 'SELECT password,id FROM users WHERE email = :email';
        $data = array(':email' => $email);

        $stmt = queryPost($dbh,$sql,$data);
          debug('クエリ実行の中身：'.print_r($stmt,true));

        $result = $stmt->fetch(PDO::FETCH_ASSOC);
          debug('クエリ結果の中身：'.print_r($result,true));

        //パスワード照合
        if(!empty($result) && password_verify($pass, array_shift($result))){
          debug('パスワードが一致しました。');

          //デフォルトを１時間に設定
          $sesLimit = 60*60;
          //最終ログイン日時を現在日時に
          $_SESSION['login_date'] = time();

          //ログイン保持にチェックがある場合
          if($pass_save){
            debug('ログイン保持にチェックがあります。');

            $_SESSION['login_limit'] = $sesLimit*24*30;

          }else{
            debug('ログイン保持にチェックはありません。');
            //次回位からログイン保持しないので、ログイン有効期限を１時間にセット
            $_SESSION['login_limit'] = $sesLimit;
          }

          $_SESSION['user_id'] = $result['id'];

          debug('セッション変数の中身；'.print_r($_SESSION,true));
          debug('マイページへ遷移します');
          header("Location:mypage.html");
        }else{
          debug('パスワードがアンマッチです。');
          $err_msg['common'] = MSG09;
        }

      } catch (Exception $e) {
        error_log('エラー発生：' .$e->getMessage());
        $err_msg['common'] = MSG07;
      }
    }
}
debug('画面表示終了 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<');
```