当用户在Angular前端应用程序的注册表单中输入错误或没有数据时,我正在使用Slim PHP尝试同时生成并显示多条验证消息。
例如,如果用户将用户名和密码字段保留为空白,则用户名和密码字段均应为空,并且应显示两条错误消息,但如果用户名错误为空白且密码已填写,则只有用户名错误。
到目前为止,我实现它的方法是抛出两个异常并将它们捕获到我的身份验证控制器中。下面是当用户单击表单上的“提交”时使这种情况发生的所有逻辑。
两个例外:
InvalidUsername.php
class InvalidUsername extends \LogicException {
public function __construct(string $message, $code = 0, Throwable $previous = null) {
parent::__construct($message, $code, $previous);
}
public function getUsernameError() {
return $this->message;
}
}
InvalidPassword.php
class InvalidPassword extends \LogicException {
public function __construct(string $message, $code = 0, Throwable $previous = null) {
parent::__construct($message, $code, $previous);
}
public function getPasswordError(){
return $this->message;
}
}
其中两个例外称为:
Username.php
class Username {
private $username, $error_message;
public function __construct(string $tainted_username) {
$cleaned_username = filter_var($tainted_username, FILTER_SANITIZE_STRING);
if($this->isUsernameValid($cleaned_username))
throw new InvalidUsername($this->error_message);
$this->username = $cleaned_username;
}
private function isUsernameValid($cleaned_username) {
return $this->isEmpty($cleaned_username) || $this->isTooShort($cleaned_username) ||
$this->isTooLong($cleaned_username) ? true : false;
}
private function isEmpty(string $username) {
return empty($username) ?
true && $this->error_message = 'A username is required' : false;
}
public function __toString() {
return $this->username;
}
}
Password.php
class Password {
private $password, $error_message;
public function __construct(string $tainted_password) {
$cleaned_password = filter_var($tainted_password, FILTER_SANITIZE_STRING);
if ($this->isPasswordValid($cleaned_password))
throw new InvalidPassword($this->error_message);
$this->password = $cleaned_password;
}
private function isPasswordValid($cleaned_password) {
return $this->isEmpty($cleaned_password) || $this->isTooShort($cleaned_password) ||
$this->isTooLong($cleaned_password) ? true : false;
}
private function isEmpty(string $password) {
return empty($password) ?
true && $this->error_message = 'A password is required' : false;
}
public function __toString() {
return $this->password;
}
}
服务和控制器类:
AuthenticateService.php
class AuthenticationService {
protected $userMapper;
public function __construct(UserMapper $userMapper) {
$this->userMapper = $userMapper;
}
public function registerUser (string $tainted_username, string $tainted_password) {
$username = new Username($tainted_username);
$password = new Password($tainted_password);
$user = new User($email, $username, $password);
return $this->userMapper->saveUser($user);
}
}
AuthenticateController.php
class AuthenticationController {
private $authenticationService;
public function __construct(AuthenticationService $authenticationService) {
$this->authenticationService = $authenticationService;
}
public function registerUser($request, $response) {
$tainted_username = $request->getParsedBody()['username'];
$tainted_password = $request->getParsedBody()['password'];
$validationResponse = null;
try {
$this->authenticationService->registerUser($tainted_username, $tainted_password);
}
catch(InvalidUsername | InvalidPassword $e) {
$validationResponse = ['usernameError' => true, 'usernameMessage' => $e->getUsernameError(),
'passwordError' => true, 'passwordMessage' => $e->getPasswordError()];
}
return $jsonResponse = $response->withJson($validationResponse);
}
}
但是它并没有真正按照预期的方式工作。我认为问题出在AuthenticationController类中registerUser()
方法的catch语句中。
如果我将用户名和密码都保留为空白,然后提交,则会收到以下答复:message: Call to undefined method App\Models\Exceptions\InvalidUsername::getPasswordError()
但是,如果我填写用户名字段并将密码保留为空白,则会收到此响应:message: Call to undefined method App\Models\Exceptions\InvalidPassword::getUsernameError()
并且如果我将用户名字段保留为空白并填写密码字段,则会收到以下响应:message: Call to undefined method App\Models\Exceptions\InvalidUsername::getPasswordError()
似乎我无法同时捕获InvalidUsername和InvalidPassword异常。似乎捕获了一个异常,然后尝试调用旨在用于另一个异常的方法。
无论如何我都能得到它,因此InvalidUsername和InvalidPassword都被同时捕获,因此getUsernameError()
和getPasswordError()
都可以被调用并用于设置传出的json响应?
[在我使用Exception getMessage()
方法之前,该方法确实有效,但是只能一次设置和显示一条错误消息。例如,它以用户名错误开头,然后,如果正确填写了用户名字段,则将其转换为密码错误,就像设置验证消息并按顺序显示一样。我很快意识到这可能是因为getMessage是最终的,这就是为什么我在每个异常中都有getUsernameError()
和getPasswordError()
方法的原因。
任何帮助将不胜感激。
public function registerUser($request, $response)
{
$tainted_username = $request->getParsedBody()['username'];
$tainted_password = $request->getParsedBody()['password'];
$validationResponse = [];
try {
$this->authenticationService->registerUser($tainted_username, $tainted_password);
} catch (InvalidUsername $e) {
$validationResponse['usernameError'] = true;
$validationResponse['usernameMessage'] = $e->getUsernameError();
}
catch (InvalidPassword $e) {
$validationResponse['passwordError'] = true;
$validationResponse['passwordMessage'] = $e->getPasswordError();
}
return $jsonResponse = $response->withJson($validationResponse);
}
我还建议使用通用消息获取器名称,而不是使用getPasswordError()和getUsernameError()为什么不使用Exception类中的通用getMessage()?类名InvalidUsername已经告诉您该对象与用户名有关,您无需在方法名中重复此信息。