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

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

ただいまの
回答率

88.58%

例外処理されてしまう原因が特定できない(PHP, MySQL)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 910

gomenne

score 12

現状

新規登録の機能を作っているが、email登録の項目で、新しいアドレスを登録しようとすると、自分で作ったDuplicateの例外処理に引っかかってしまう。
その原因が特定できない。

signup.php

<?php

 // 新規登録

 require_once(__DIR__ . '/../config/config.php');

 $app = new MyApp\Controller\Signup();

 $app->run();

  ?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Sign Up</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="container">
    <form action="" method="post" id="signup">
      <p>
        <input type="text" name="email" placeholder="email" value="<?= isset($app->getValues()->email) ? h($app->getValues()->email) : ''; ?>">
      </p>
      <p class="err"><?= h($app->getErrors('email')); ?></p>
      <p>
        <input type="password" name="password" placeholder="password">
      </p>
      <p class="err"><?= h($app->getErrors('password')); ?></p>
      <div class="btn" onclick="document.getElementById('signup').submit();">Sign Up</div>
      <p class="fs12"><a href="/login.php">Log In</a></p>
      <input type="hidden" name="token" value="<?= h($_SESSION['token']); ?>">
    </form>
  </div>
</body>
</html>

 Signup.php 

<?php

namespace MyApp\Controller;

class Signup extends \MyApp\Controller {

  public function run() {
    if ($this->isLoggedIn()) {
      header('Location: ' . SITE_URL);
      exit;
    }

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
      $this->postProcess();
    }
  }


  protected function postProcess() {
    // validate
      try {
        $this->_validate();
      } catch (\MyApp\Exception\InvalidEmail $e) {
        // echo $e->getMessage();
        // exit;
        $this->setErrors('email', $e->getMessage());
      } catch (\MyApp\Exception\InvalidPassword $e) {
        // echo $e->getMessage();
        // exit;
        $this->setErrors('password', $e->getMessage());
      }

      // echo "success";
      // exit;

      $this->setValues('email', $_POST['email']);

      if ($this->hasError()) {
        return;
      } else {
        // create user
        try{
          $userModel = new \MyApp\Model\User();
          $userModel->create([
            'email' => $_POST['email'],
            'password' => $_POST['password']
          ]);
        } catch (\MyApp\Exception\DuplicateEmail $e) {
          $this->setErrors('email', $e->getMessage());
          return;
        }

        // redirect to login
        header('Location: ' . SITE_URL . '/login.php');
        exit;
      }
  }

  private function _validate() {
    if (!isset($_POST['token']) || $_POST['token'] !== $_SESSION['token']) {
      echo 'Invalid Token!';
      exit;
    }
    if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
      throw new \MyApp\Exception\InvalidEmail();
    }

    if (!preg_match('/\A[a-zA-Z0-9]+\z/', $_POST['password'])) {
      throw new \MyApp\Exception\InvalidPassword();
    }
  }

}

 ?>

 Model.php 

<?php

namespace MyApp;

class Model {
  protected $db;

  public function __construct() {
    try {
      $this->db = new \PDO(DSN, DB_USERNAME, DB_PASSWORD);
    } catch (\PDOException $e) {
      echo $e->getMessage();
      exit;
    }
  }
}

 ?>

User.php  

<?php

namespace MyApp\Model;

class User extends \MyApp\Model {
  public function create($values) {
    $stmt = $this->db->prepare("insert into users (email, password, created, modified) values (:email, :password, now(), now())");
    $res = $stmt->execute([
      ':email' => $values['email'],
      ':password' => password_hash($values['password'], PASSWORD_DEFAULT)
    ]);
    if ($res === false) {
      throw new \MyApp\Exception\DuplicateEmail();
    }
  }
}

 ?>

 DuplicateEmail.php 

<?php

namespace MyApp\Exception;

class DuplicateEmail extends \Exception {
  protected $message = 'Duplicate Email!';
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2018/11/14 05:50

    テーブル定義のcreate文とサンプルデータのinsert文をご提示ください

    キャンセル

回答 1

checkベストアンサー

0

全体的にみて問題はなさそうですがデバッグ方法として

「$this->db = new \PDO()」でdbのインスタンスをつくったら

  $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 


でとりあえず例外を拾えるようにし

  try{
    $stmt = $this->db->prepare("insert into users (email, password, created, modified) values (:email, :password, now(), now())");
    $res = $stmt->execute([
      ':email' => $values['email'],
      ':password' => password_hash($values['password'], PASSWORD_DEFAULT)
    ]);
  }catch(PDOException $e){
    die($e->getMessage());
  }


で、SQL側がエラーを吐いていないか確認する
あとは例えば「insert into users」にスタティックに値を渡して確かめる

あたりからでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る