0

当用户在我的 Angular 前端应用程序的注册表单中输入不正确或没有数据时,我正在使用 Slim PHP 尝试同时生成和显示多个验证消息。

例如,如果用户将用户名和密码字段留空,则用户名和密码字段都为空时应该有两条错误消息,但如果用户名错误为空且密码已填写,则只有用户名错误。

到目前为止,我实现它的方式是抛出两个异常并在我的身份验证控制器中捕获它们。以下是当用户单击表单上的提交时发生这种情况的所有逻辑。

两个例外:

无效用户名.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;
    }
}

无效密码.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;
    }
}

调用这两个异常的地方:

用户名.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;
    }
}

密码.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);
    }
}

验证控制器.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);
    }
}

但是,它并没有真正按预期工作。我认为问题在于registerUser()AuthenticationController类中方法的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()andgetPasswordError()都可以被调用并用于设置传出的 json 响应?

在我使用 ExceptiongetMessage()方法之前,该方法确实有效,但它只能一次设置和显示一条错误消息。例如,它以用户名错误开始,然后如果正确填写了用户名字段,则转换为密码错误,几乎就像验证消息被设置并按顺序显示一样。我很快意识到这可能是因为 getMessage 是最终的,这就是为什么我在每个异常中 都有getUsernameError()和方法。getPasswordError()

任何帮助,将不胜感激。

4

1 回答 1

0

试试这个 registerUser 方法:

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 已经告诉您该对象是关于用户名的,您不需要在方法名称中复制此信息。

于 2019-12-02T17:41:45.840 回答