2017-11-30 4 views
1

ユーザーを登録するための確認フォームがあります。このモデルの入力データの検証にはtry-catchingという概念を試しています。私が最初にあなたに私のコードをお見せしましょう:検証フォームで複数の例外をキャッチするには

モデル登録

public function register (string $username, string $email, string $email_repeat, string $password, string $password_repeat, string $ip, string $reCaptcha) { 
    $this->username = trim($username); 
    $this->email = trim($email); 
    $this->email_repeat = trim($email_repeat); 
    $this->password = $password; 
    $this->password_repeat = $password_repeat; 
    $this->ip = $ip; 
    $this->reCaptcha_response = $reCaptcha; 
    $this->reCaptcha = new ReCaptcha(GOOGLE_CAPTCHA_SECRET); //the API secret is in the config.php file 

    $this->verifyEmail(); 
    $this->verifyUsername(); 
    $this->verifyPassword(); 
    $this->validateReCaptcha($this->reCaptcha_response, $this->ip); 

    $this->db->insertRow("INSERT INTO users (username, password, email) VALUES (?, ?, ?)", [$this->username, $this->password, $this->email]); 
} 

public function verifyEmail() { 
    if(empty($this->email) || empty($this->email_repeat)) { 
     throw new \Exception('Email address is empty'); 
    } 

    $isTaken = $this->db->getRow("SELECT COUNT(*) as count FROM users WHERE email= ?", [$this->email]); 
    if($isTaken->count > 0){ 
     throw new \Exception('This email is taken'); 
    } 
} 


private function verifyUsername() { 
    if(strlen($this->username) < 3 || strlen($this->username) > 15) { 
     throw new \Exception('Username must be between 3 and 15 symbols'); 
    } 

    $isTaken = $this->db->getRow("SELECT COUNT(*) as count FROM users WHERE username= ?", [$this->username]); 
    if($isTaken->count > 0){ 
     throw new \Exception('This username is taken'); 
    } 
} 

コントローラ:あなたがモデルで見ることができるように

public function register() 
{ 
    if($this->post != null) { 
     try { 
      $register = $this->tableRegister->register(
       $_POST['username'], 
       $_POST['email'], 
       $_POST['email_repeat'], 
       $_POST['password'], 
       $_POST['password_repeat'], 
       $_SERVER['REMOTE_ADDR'], 
       $_POST['g-recaptcha-response'] 
      ); 
     } catch (\Exception $err) { 
      $this->flashMessage->error($err->getMessage()); 
     } 
    } 
    $this->renderView('users/register'); 
} 

は、両方の方法validateEmailvalidateUsernameがデータベースを通過しているかどうかをチェック電子メールまたはユーザー名が使用されます。両方とも奪取された場合、私は例外を捕捉したいだけでなく、電子メールを受け取った場合、ユーザ名を取得した場合、ユーザ名が無効な場合に発生する可能性があるその他の例外もすべて捕捉したい。現在、私のスクリプトは最初の例外で終了します。これどうやってするの?

答えて

2

例外がスローされると、ステートメントに続くコードは に実行されず、PHPは最初に一致するキャッチブロックを見つけようとします。 ハンドラがset_exception_handler()(source)で定義されていない限り、例外がキャッチされない場合、 の "Uncaught Exception ..."メッセージでPHP致命的エラーが発生します。ここ

良い解決策は、モデルのhasErrorsgetErrors方法をerrorsプロパティを追加することです。これにより、各フォームフィールドのエラーチェックを格納して処理することができます。例えば

if (!$this->hasErrors()) { 
    $this->db->insertRow("INSERT INTO users (username, password, email) VALUES (?, ?, ?)", 
    [$this->username, $this->password, $this->email]); 
} 

次に、あなたのコントローラのチェックを追加します:

if ($this->tableRegister->hasErrors()) { 
    $this->flashMessage->error('The form has error(s): ' 
     .implode("; \r\n", $this->tableRegister->getErrors())); 
} else { 
    // code for user registration here 
} 
+0

ありがとうございます。私はその時点で1つのエラーを持っていることにしましたが、詳細な答えにもかかわらずありがとうございました。 – pidari

+0

あなたは大歓迎です、@pidari。 – camelsWriteInCamelCase

0

モデルregister関数にtry-catchが必要です(例:

public function register (string $username, string $email, string $email_repeat, string $password, string $password_repeat, string $ip, string $reCaptcha) { 
    try{ 
     $this->username = trim($username); 
     $this->email = trim($email); 
     $this->email_repeat = trim($email_repeat); 
     $this->password = $password; 
     $this->password_repeat = $password_repeat; 
     $this->ip = $ip; 
     $this->reCaptcha_response = $reCaptcha; 
     $this->reCaptcha = new ReCaptcha(GOOGLE_CAPTCHA_SECRET); //the API secret is in the config.php file 

     $this->verifyEmail(); 
     $this->verifyUsername(); 
     $this->verifyPassword(); 
     $this->validateReCaptcha($this->reCaptcha_response, $this->ip); 

     $this->db->insertRow("INSERT INTO users (username, password, email) VALUES (?, ?, ?)", [$this->username, $this->password, $this->email]); 
    } catch(\Exception ex){ 
     //handle error 
     throw new \Exception("Error registering user"); //this will pass the exception up to the calling method instead of just killing the page 
    } 
} 

いずれかverifyEmailまたはverifyUsernameスローエラーならば、これらは、実行中のコードの残りの部分を停止します。彼らは正しく処理されないので、ページ全体の実行を停止します。

希望すると便利です。

+0

私はあなたが何を意味するか見

public function verifyEmail() { if(empty($this->email) || empty($this->email_repeat)) { $this->errors['email'] = 'Email address is empty'; return false; } $isTaken = $this->db->getRow("SELECT COUNT(*) as count FROM users WHERE email= ?", [$this->email]); if($isTaken->count > 0){ $this->errors['email'] = 'This email is taken'; return false; } return true; } public function hasErrors() { return !empty($this->errors); } public function getErrors() { return $this->errors; } 

がモデルでregisterメソッドにチェックを追加します。しかし、これは5つの異なる方法に対して5種類のtry-catchを持つことは醜いでしょう。 – pidari

+0

私は同意します。しかし、あなたのシナリオでは、電子メールまたはユーザー名のいずれかが間違っていると失敗する必要があります。そのメソッドの全体をtry-catchでラップしてください – Luke

関連する問題