我有一个用于注册用户的验证表单,我正在尝试使用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');
}
正如您在模型中看到的,方法validateEmail
和validateUsername
都通过数据库并检查是否采用了电子邮件或用户名。如果两者都被采用,我想要捕获两个例外,以及可能发生的所有其他异常 - 如果采用电子邮件,如果使用用户名,如果用户名无效......一切。目前我的脚本在第一个例外结束。我怎样才能做到这一点?
答案 0 :(得分:2)
抛出异常时,语句后面的代码不会 执行,PHP将尝试找到第一个匹配的catch块。 如果未捕获异常,将发出PHP致命错误 &#34;未捕获的例外......&#34;消息,除非已定义处理程序 使用set_exception_handler()(source)。
这里一个好的解决方案是为模型添加errors
属性,hasErrors
和getErrors
方法。这将允许您存储和处理每个表单字段的错误检查。
例如:
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
}
}
如果verifyEmail
或verifyUsername
抛出错误,则会阻止其余代码执行。由于未正确处理,因此停止执行整个页面。
希望这有帮助!