如何在验证表单中捕获多个例外

时间:2017-11-30 19:02:30

标签: php exception-handling

我有一个用于注册用户的验证表单,我正在尝试使用try-catch的概念来验证模型中的输入数据。我先告诉你我的代码:

模型注册

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 个答案:

答案 0 :(得分:2)

  

抛出异常时,语句后面的代码不会   执行,PHP将尝试找到第一个匹配的catch块。   如果未捕获异常,将发出PHP致命错误   &#34;未捕获的例外......&#34;消息,除非已定义处理程序   使用set_exception_handler()(source)。

这里一个好的解决方案是为模型添加errors属性,hasErrorsgetErrors方法。这将允许您存储和处理每个表单字段的错误检查。

例如:

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方法:

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
}

答案 1 :(得分: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
    }
}

如果verifyEmailverifyUsername抛出错误,则会阻止其余代码执行。由于未正确处理,因此停止执行整个页面。

希望这有帮助!