🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

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

セッション

Sessionはクライアントがサーバに送ったすべてのリクエストのことを指します。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Q&A

解決済

3回答

2652閲覧

PHP セッションを維持できない。

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

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

セッション

Sessionはクライアントがサーバに送ったすべてのリクエストのことを指します。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

0グッド

1クリップ

投稿2021/02/20 14:05

以下、PHPでCRUDを作成しています。

PHPでユーザー登録後、ログイン情報を取得できずに詰まっています。
実際に投稿しようと思った際、ユーザー情報を取得できずにログイン画面にいってしまいます。
こちら、調べてみたり、公式ドキュメントを読んだのですが、解決策が見つからず、原因わかる方いますか?

イメージ説明

ログイン情報を確保したいのですが、以下のようになってしまいます。

//users/login.php <?php require('../common/head_info.php'); ?> <?php require('../common/database.php'); require('../common/auth.php'); //POST送信された場合 if(!empty($_POST)) { $email=$_POST['email']; $pass = $_POST['pass']; //未入力チェック validateNot($email,'email'); validateNot($pass,'pass'); if(empty($err_msg)) { if(empty($err_msg)) { $database_handler = getDatabaseConnection(); if ($statement = $database_handler->prepare('SELECT id, name, password FROM users WHERE email = :email')) { $statement->bindParam(':email', $email); $statement->execute(); } header('Location: ../tweets/index.php'); } } } ?> <div class='main-top'> <div class='form-login'> <div class="form-login-list"> <form action="" method='post' class='form'> <label> <input type="text" name='email' placeholder="メールアドレス" value="<?php print(htmlspecialchars($_POST['email'],ENT_QUOTES));?>"> <div class="error_mes"> <?php if(!empty($err_msg['email'])) echo $err_msg['email']; ?> </div> </label> <label> <input type="password" name='pass' placeholder="パスワード" value="<?php print(htmlspecialchars($_POST['pass'],ENT_QUOTES));?>"></br> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> <span class='form-rule'>※英数字8文字以上</span> </label> <label> <input type="checkbox" name='pass_save'>次回ログインを省略する </label> <div class='button-container'> <input type="submit" value='ログインする'> </div> </form> </div> </div> </div>
//common/database.php <?php define('message01', '入力必須です'); define('message02', 'ニックネームは256文字以内で入力してください。'); define('message03', 'パスワードは256文字以内で入力してください。'); define('message04', 'パスワードは半角英数字8文字以上で入力してください。'); //================================ // ログ //================================ //画面にエラーを表示させるか ini_set('display_errors', 'On'); //ログを取るか ini_set('log_errors', 'On'); //ログの出力ファイルを指示 ini_set('error_log', 'php.log'); session_start(); /** * PDOを使ってデータベースに接続する * @return PDO */ function getDatabaseConnection() { try { $database_handler = new PDO('mysql:dbname=aaa;host = 127.0.0.1;port=8889;charset=utf8', 'root', 'root'); } catch (PDOException $e) { echo "DB接続に失敗しました。<br />"; echo $e->getMessage(); exit; } return $database_handler; } // //================================= // //エラーメッセージ格納用の配列 // //================================= $err_msg = array(); //未入力チェック function validateNot($str,$value){ if(empty($str)) { global $err_msg; $err_msg[$value] = message01; } } //ニックネームの最大文字数チェック function validateNameMaxLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)>256){ global $err_msg; $err_msg[$value] = message02; } } //パスワードの最大文字数チェック function validatePassMaxLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)>256){ global $err_msg; $err_msg[$value] = message03; } } //パスワードの最小文字数チェック function validatePassMinLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)<8){ global $err_msg; $err_msg[$value] = message04; } }
//common/head_info.php <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet"> <link rel="stylesheet" href="../public/css/style.css"> </head> <body> <script src='https://code.jquery.com/jquery-3.4.1.min.js'></script> </body>
//tweets/create.php <?php require('../common/head_info.php'); require('../common/database.php'); require('../common/auth.php'); ?> <?php if (!isLogin()) { header('Location: ../users/login.php'); exit; } $user_id = getLoginUserId(); $database_handler = getDatabaseConnection(); //post送信されていた場合 if(!empty($_POST)) { //バリデーションチェック $title = (isset($_POST['title'])) ? $_POST['title'] : ''; $content = (isset($_POST['content'])) ? $_POST['content'] : ''; print_r('debug',$title); print_r('debug',$content); // //最大文字数チェック // validMaxLen($comment, 'comment'); // //未入力チェック // validNotEntered($comment, 'comment'); if(empty($err_msg)) { //例外処理 try { //DB接続 $database_handler = getDatabaseConnection(); // プリペアドステートメントで SQLをあらかじめ用意しておく $statement = $database_handler->prepare('INSERT INTO tweets (user_id, title, content) VALUES (user_id, :title, :content)'); //指定された変数名にパラメータをバインド(紐付け) $statement->bindParam(':title', ($title)); $statement->bindParam(':content', ($content)); $statement->bindParam(':user_id', ($user_id)); $statement->execute(); $_SESSION['select_memo'] = [ 'id' => $database_handler->lastInsertId(), 'title' => $title, 'content' => '', ]; //クエリ成功の場合 if($statement) { $_POST = array(); //postをクリア header('Location:../tweets/index.php'); //自分自身に遷移する exit(); } } catch(Exception $e) { error_log('エラー発生:'. $e->getMessage()); } } } ?> <?php if(!empty($_SESSION['user_id'])) { ?> <div class="main-top"> <form action="" method='post' class='form review-form'> <div class='button-containers'> <div class="tweet-header">aaaa</div> <div class="tweet-body"> <div class="tweet-tops"> <label> <input type="text" name='title' placeholder="タイトル"> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> </label> <label> <textarea name="content" cols="82" rows="10" class='review-textarea'></textarea> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> </label> <div class='button-container'> <input type="submit" value='投稿する'> </div> </div> </div> </div> </form> </div> <?php } ?>
<?php require('../common/head_info.php'); require('../common/database.php'); require('../common/auth.php'); ?> <?php if (!isLogin()) { header('Location: ../users/login.php'); exit; } $user_id = getLoginUserId(); $database_handler = getDatabaseConnection(); //post送信されていた場合 if(!empty($_POST)) { //バリデーションチェック $title = (isset($_POST['title'])) ? $_POST['title'] : ''; $content = (isset($_POST['content'])) ? $_POST['content'] : ''; print_r('debug',$title); print_r('debug',$content); if(empty($err_msg)) { //例外処理 try { //DB接続 $database_handler = getDatabaseConnection(); $statement = $database_handler->prepare('INSERT INTO tweets (user_id, title, content) VALUES (user_id, :title, :content)'); //指定された変数名にパラメータをバインド(紐付け) $statement->bindParam(':title', ($title)); $statement->bindParam(':content', ($content)); $statement->bindParam(':user_id', ($user_id)); $statement->execute(); $_SESSION['select_memo'] = [ 'id' => $database_handler->lastInsertId(), 'title' => $title, 'content' => '', ]; //クエリ成功の場合 if($statement) { $_POST = array(); //postをクリア header('Location:../tweets/index.php'); //自分自身に遷移する exit(); } } catch(Exception $e) { error_log('エラー発生:'. $e->getMessage()); } } } ?> <?php if(!empty($_SESSION['user_id'])) { ?> <div class="main-top"> <form action="" method='post' class='form review-form'> <div class='button-containers'> <div class="tweet-header">aaa</div> <div class="tweet-body"> <div class="tweet-tops"> <label> <input type="text" name='title' placeholder="タイトル"> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> </label> <label> <textarea name="content" cols="82" rows="10" class='review-textarea'></textarea> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> </label> <div class='button-container'> <input type="submit" value='投稿する'> </div> </div> </div> </div> </form> </div> <?php } ?>

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/02/20 22:19

こちら、なにかの教材のコードでしょうか? つぎはぎ感がすごいので、丸々使っているわけではなさそうですが、元があるのであれば、質問に追記しておいてください。
m.ts10806

2021/02/21 05:01

>公式ドキュメントを読んだのですが 量が膨大なので、きちんとURLで確認した先を提示してください。「調べたけどわからない」と言ってるのと同じで、情報量ゼロです
guest

回答3

0

まず初めに、ちょっと眠いので全部コードを読まないことをお詫びいたします。

結論 SESSIONの使い方をもう少し勉強した方が良いかも?

草木も眠る丑三つ時…ってことで少し巻きで回答してみます。

  1. session_start();phpの開始タグの直後に書くのが推奨だった気がします
  2. セッションを使いたいファイルすべてにsession_start();が必要だった気がします
  3. if(!empty($_SESSION['user_id'])って判定してるけどそもそも代入をしてないような?

セッションの開始はあまり厳密にやらなくてもセッション使う前なら動いたような気がしますが、
推奨される位置が先頭ですので、素直に先頭に置きましょう。

セッションも「関数」と捉えると、使いたいファイルの先頭で呼び出さないと関数が動いてくれないということが納得できるかもしれません。
※javascriptとかでも呼び出してない関数は動いてくれないのです。

セッション保持できないとのことですが、F検索してもコード内に代入してる箇所が見当たらないです。
$_SESSION['user_id']$user_idは別物です。
$_SESSION['select_memo']には代入してるけどidだし、セッション名も違うから関係なさそう。
ユーザー情報を保持したいのであれば、 $_SESSION['user_id']ここに入れましょう。

昔ハマりました。3つ全部ハマりましたよ。
誰しも通る道なのだよ…ということで頑張ってくださいっ

参考URL php公式
https://www.php.net/manual/ja/session.examples.basic.php

ps 4.if (!isLogin()とあるけど、代入しているところが見当たらないですね…

php

1if (!isLogin()) { 2 header('Location: ../users/login.php'); 3 exit; 4}

ログイン情報も保持されてないかも。
$_SESSION['isLogin']としてフラグ立てるかどうかかな。
キャメルとスネークでちょっと違和感あるけどお好みでどうぞ。

以下蛇足です。
getDatabaseConnection()は定義されているけど、
getLoginUserId()こっちが見当たらないです。
他のファイルかな?と推察しつつ床につきます。おやすみなさいませ。

投稿2021/02/20 18:36

編集2021/02/20 18:37
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hoshi-takanori

2021/02/20 20:15

勝手に補足しますが、 Warning: session_start(): Cannot start session when headers already sent という警告は出てませんか? (エラー表示レベルに警告を含める設定が必要かも。) PHP のセッションが機能するには HTTP ヘッダーにクッキー情報を書き込む必要がありますが、HTML コンテンツ (<!DOCTYPE> や <head> を含む) を出力すると自動的に HTTP ステータスやヘッダーが出力されてしまうので、その後でクッキーを含む HTTP ヘッダーを出力することはできず、セッションが機能しなくなります。 で、require の順番が require('../common/head_info.php'); require('../common/database.php'); になってますが、head_info.php で HTML ヘッダーを出力しているので、その後 database.php で session_start() してももう遅いです。(クッキーに限らず、HTTP ステータスやその他のヘッダー情報を指定したくなる場合はいろいろあるので、head_info.php を最初に require するのはお勧めできません。) また、 <?php require('../common/head_info.php'); require('../common/database.php'); require('../common/auth.php'); ?> <?php のように、require 部分だけをひとつの <?php 〜 ?> タグに分けてますが、?> と次の <?php の間に空行があるとそこで空行を出力します。この空行も HTML コンテンツの一部とみなされて、HTTP ステータスやヘッダーが未出力であればここで出力されてしまいますので、このような書き方はお勧めできません。(気持ちは分かりますけどね…。)
m.ts10806

2021/02/20 23:09

実装としては下記は考慮したいところですね。 > https://www.php.net/manual/ja/language.basic-syntax.phptags.php > ファイルが PHP コードのみを含む場合は、ファイルの最後の終了タグは省略するのがおすすめです。 終了タグの後に余分な空白や改行があると、予期せぬ挙動を引き起こす場合があるからです。 余分な空白や改行のせいで PHP が出力バッファリングを開始し、その時点の内容を意図せず出力してしまうことになります。
退会済みユーザー

退会済みユーザー

2021/02/21 04:15

はい、session_start(): Cannot start session when headers already sentが出ています。
guest

0

ベストアンサー

こちらは一度閉じます。

投稿2021/02/21 06:46

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2021/02/21 08:39

こちら解決しました。結果として、保存されているパスワードに問題がありました。
guest

0

以下のように記述変更してみましたが、相変わらずログインできません。
原因何かわかりますか?

//users/login.php <?php require('../common/function.php'); require('../common/database.php'); require('../common/head_info.php'); ?> <?php require('../common/auth.php'); ?> <?php //POST送信された場合 if(!empty($_POST)) { $email=$_POST['email']; $pass = $_POST['pass']; //未入力チェック validateNot($email,'email'); validateNot($pass,'pass'); if(empty($err_msg)) { //メールアドレスの重複チェック //メールアドレスの形式チェック //パスワードの最大文字数チェック validatePassMaxLen($pass,'pass'); //パスワードの最小文字数チェック validatePassMinLen($pass,'pass'); //パスワードの半角英数字チェック if(empty($err_msg)) { $database_handler = getDatabaseConnection(); // プリペアドステートメントで SQLをあらかじめ用意しておく if ($statement = $database_handler->prepare('SELECT id, name, password FROM users WHERE email = :email')) { $statement->bindParam(':email', $email); $statement->execute(); $user = $statement->fetch(PDO::FETCH_ASSOC); print_r('debug',$user); if (!$user) { $_SESSION['errors'] = [ 'メールアドレスまたはパスワードが間違っています。' ]; header('Location: ../users/login.php'); exit; } $name = $user['name']; $id = $user['id']; if (password_verify($pass, $user['pass'])) { // ユーザー情報保持 $_SESSION['user'] = [ 'name' => $name, 'id' => $id ]; // 更新日が最新のメモ情報保持 if ($statement = $database_handler->prepare("SELECT id, title, content FROM memos WHERE user_id = :user_id ORDER BY updated_at DESC LIMIT 1")) { $statement->bindParam(":user_id", $id); $statement->execute(); $result = $statement->fetch(PDO::FETCH_ASSOC); if ($result) { $_SESSION['select_tweets'] = [ 'id' => $result['id'], 'title' => $result['title'], 'content' => $result['content'] ]; } } header('Location: ../tweets/index.php'); exit; } else { $_SESSION['errors'] = [ 'メールアドレスまたはパスワードが間違っています。' ]; header('Location: ../users/login.php'); exit; } } } } } ?> <?php require('../common/header.php'); ?> <div class='main-top'> <div class='form-login'> <div class="form-login-list"> <h2><i class="fas fa-sign-in-alt"></i>ログイン</h2> <section class='guestuser'> ゲストユーザー用 <p><i class="far fa-envelope"></i>メールアドレス:guest@mail.com</p> <p><i class="fas fa-unlock-alt"></i>パスワード:guestuser</p> </section> <form action="" method='post' class='form'> <label> <input type="text" name='email' placeholder="メールアドレス"> <div class="error_mes"> <?php if(!empty($err_msg['email'])) echo $err_msg['email']; ?> </div> </label> <label> <input type="password" name='pass' placeholder="パスワード"></br> <div class="error_mes"> <?php if(!empty($err_msg['pass'])) echo $err_msg['pass']; ?> </div> <span class='form-rule'>※英数字8文字以上</span> </label> <label> <input type="checkbox" name='pass_save'>次回ログインを省略する </label> <div class='button-container'> <input type="submit" value='ログインする'> </div> </form> </div> </div> </div> <?php require('../common/footer.php'); ?>
//function.php <?php define('message01', '入力必須です'); define('message02', 'ニックネームは256文字以内で入力してください。'); define('message03', 'パスワードは256文字以内で入力してください。'); define('message04', 'パスワードは半角英数字8文字以上で入力してください。'); //================================ // ログ //================================ //画面にエラーを表示させるか // ini_set('display_errors', 'On'); //ログを取るか ini_set('log_errors', 'On'); //ログの出力ファイルを指示 ini_set('error_log', 'php.log'); //セッションを使う session_start(); // //================================= // //エラーメッセージ格納用の配列 // //================================= $err_msg = array(); //未入力チェック function validateNot($str,$value){ if(empty($str)) { global $err_msg; $err_msg[$value] = message01; } } //ニックネームの最大文字数チェック function validateNameMaxLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)>256){ global $err_msg; $err_msg[$value] = message02; } } //パスワードの最大文字数チェック function validatePassMaxLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)>256){ global $err_msg; $err_msg[$value] = message03; } } //パスワードの最小文字数チェック function validatePassMinLen($str,$value){ //全角も半角も1文字として扱う if(mb_strlen($str)<8){ global $err_msg; $err_msg[$value] = message04; } }
//database.php <?php /** * PDOを使ってデータベースに接続する * @return PDO */ function getDatabaseConnection() { try { $database_handler = new PDO('mysql:dbname=aaa;host = 127.0.0.1;port=8889;charset=utf8', 'root', 'root'); } catch (PDOException $e) { echo "DB接続に失敗しました。<br />"; echo $e->getMessage(); exit; } return $database_handler; }

投稿2021/02/21 04:18

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

m.ts10806

2021/02/21 05:00

回答ではなく、質問本文に追記を。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問