MVC最佳实践声明模型应该处理输入/数据验证。假设我们有一个创建新用户帐户的模型,其中包含以下字段和约束:
Username - not null, not already in DB
Password - not null, alphanumeric only
E-mail - not null, not already in DB, valid e-mail format
我们有AccountModel
CreateNewUser()
函数:
component
{
public void function CreateNewUser(string username, string password, string email)
{
// create account
}
}
然后我们有一个处理表单的控制器,并告诉模型创建帐户:
component
{
public void function NewUser()
{
var username = event.getValue("username");
var password = event.getValue("password");
var email = event.getValue("email");
var accountModel = new AccountModel();
accountModel.CreateNewUser(username, password, email);
event.addResult("UserCreated");
}
现在我想添加验证。如果用户无法为所有三个字段提供输入,则应用程序应向用户显示三条验证错误消息。这在控制器中很容易做到:
// assumes that ValidateInput() is a function on the controller that returns an array
var validationErrors = ValidateInput(username, password, email);
// if there were any validation errors, return a ValidationError result
if (len(validationErrors)
{
event.setValue("validationerrors", validationErrors);
event.addResult("ValidationError");
}
else
{
event.addResult("UserCreated");
}
视图将拉出validationerrors变量并显示错误消息。
但是,这个逻辑应该存在于模型中。我该怎么做呢?我可以想到两种方式:
方法1:将ValidateInput()
从控制器移至模型。现在,控制器必须先在ValidateInput()
之前调用CreateNewUser()
。如果程序员忘记执行此操作,CreateNewUser()
将抛出验证异常。这样做的缺点是,现在每个需要验证的数据操作都需要一个if / else块。
方法2 :Forego必须致电ValidateInput()
并直接致电CreateNewUser()
。如果存在任何验证错误,将抛出异常并且它将包含错误消息数组。此方法可以在C#中使用,但看起来ColdFusion不支持返回带有异常的数据,只支持异常消息和类型。此外,每个数据操作都需要try / catch块。
方法3: ??
在这种情况下,您将如何处理验证?方法1是大多数人在模型中进行验证时所做的事情吗?或者人们通常使用方法2?或者是否有一个我没想到的方法3?
答案 0 :(得分:0)
我认为您不应该将用户数据条目的验证与用户帐户的创建结合起来:它们是完全不同的东西。
如果你把两者结合在一起,这意味着你每次创建一个帐户时都会进行表单验证,这对我来说似乎不对。
我认为表单验证是一个UI问题,而不仅仅是对可能最终根据该数据创建的对象的关注。显然,您的createNewUser()方法有自己的业务规则(可能与创建新用户表单的验证非常接近,但它们仍然是单独的问题。)
这可能有点非正统,但我会在我的用户CFC中放置一个validateUserData()(或其他)方法,然后表单验证模型会调用它来帮助验证。这意味着用户的业务规则位于同一位置,可以单独调用。此后,createNewUser()处理垃圾进/出垃圾原理。
旁注:createNewUser()是一个同义反复的名字,不是吗?除了新用户之外,您还会创建哪种其他类型的用户?另外,如果它在你的Account.cfc中;是新用户还是正在创建的新帐户?如果帐户和用户不是同义词,并且帐户可能在没有用户的情况下存在(反之亦然),那么也许您应该拥有User.cfc。然后,你给我们的这段代码可能仅仅是为了说明的目的,而且你已经涵盖了所有这些。