繁体   English   中英

模型现在正在执行数据/表单验证。 如何将用户友好的错误消息返回到视图?

[英]Model now doing data/form validation. How to return user friendly error messages to the view?

从今天开始,我开始在模型层而不是控制器中验证表单数据。 我将尽可能缩短代码段。

这是我的User域对象中的一个方法( setLastName()方法基本相同)

public function setFirstName($firstName) {

    if(!$firstName) throw new \InvalidArgumentException('Some message');
    if( strlen($firstName) < 2  || strlen($firstName) > 20 ) throw new \LengthException('Some message');
    if(preg_match('/[^a-zA-Z\'.-\s]/', $firstName)) throw new FormatException('Some message');

    $this->firstName = $firstName;
}

在我的控制器中,我有这样的东西

$userService = $this->serviceFactory->build('User');

try {
    $userService->register('John', 'M');
} 
catch(\InvalidArgumentException $ex) {

}
catch(\LengthException $ex) {

}
catch(etc etc)

在我的UserService方法register()我有类似

$user->setFirstName($firstName);
$user->setLastName($lastName);

运行setFirstName()方法时,它将成功设置提供的名字。 setLastName()方法将抛出一个LengthException因为它太短了。

那就是我想要的,但是当返回到服务层然后到控制器时,我抓住了它,我知道抛出了LengthException ,但是我无法向用户提供诸如“提供的姓氏太短”的正确消息”,因为我不知道该异常是针对哪个字段抛出的,仅是异常的类型。

我该如何解决? 谢谢。

视图实例应从模型层请求信息。 控制器不负责传递信息。

这也意味着您强迫性地使用导致抽象层泄漏的异常是完全没有意义的。 “错误”只是模型层的一种状态。 这是一种预期的情况,并非例外。

MVC中的控制器负责更改模型层的状态和(很少)更改当前视图实例的状态。 他们不应从服务中收到任何反馈。

为什么不返回有用的错误消息 ,而不是返回某些消息 ,例如“提供的名字太短” 然后可以将其返回给用户。

另外,您可以看到扩展例外时可以指定其他信息,例如数字代码-您当然可以使用它。

或者当然,您可以为不同的情况创建Exception的子类,但是最终可能会产生数百个Exception子类,这当然很麻烦。

我也有同样的问题。 我认为大多数说所有验证都应该在模型中完成的人自己从来没有开发过完整的PHP MVC应用程序,只知道书籍和理论。 从来没有人看到有关该主题的代码。

无论如何,我想到了一个可能的解决方案。 您如何看待以下代码:

// Controller

$user = User::make(
    $_POST['lastname'], $_POST['firstname'], 
    $_POST['gender'], [...]
);
if(is_array($user)) {
    // store the errors in a view variable and forward, or store in session and redirect
    $_SESSION['errors'] = $user;
    $this->_redirect('add');
    exit;
}

// Model

public static make($lastname, $firstname, $gender, [...]) {
    $errors = array();
    if(/* test firstname */) $errors[] = 'model_error_firstname';
    if(/* test lastname */) $errors[] = 'model_error_lastname';
    if(!empty($errors)) return $errors;

    return new User($lastname, $firstname, $gender, [...]);
}

该模型将具有静态函数,该函数将在出错时返回带有错误的数组,或者在验证正常的情况下返回新的模型对象。

在您的控制器中,您测试是否返回了数组。

也许我会将User的构造函数设置为私有,因为如果直接用该构造函数构建用户,则将跳过所有验证。 但这并不意味着它成为一个Singleton。

也许我还要在将表单域传递给模型之前对表单域进行清理并使其安全。

诸如model_error_xyz之类的键将在带有适当文本的翻译文件中找到。

更新:

实际上,我认为您可以从构造函数中抛出一个自定义异常,该异常包含一个消息数组。 但是我之所以没有提出这个建议,是因为它导致了一半构造的对象,至少在Java中如此,但是嘿,PHP不是Java ...

您还必须验证每个setter函数:(在模型实例中进行验证似乎很麻烦。

任何想法都欢迎。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM