Php 不使用多个返回类型的OOP表单验证
我有一个用户可以登录的程序。我有一个Php 不使用多个返回类型的OOP表单验证,php,forms,oop,validation,Php,Forms,Oop,Validation,我有一个用户可以登录的程序。我有一个User类,当他们登录时,他们的所有属性(权限、用户名、真实姓名等)都保存为类属性。但是,由于所有数据都需要验证,因此我很难集中精力思考让用户更新自己信息的最佳方法 目前,当用户尝试更新其自己的信息(例如其电子邮件地址)时,我会: // Set new email $try = $user->setEmail($_POST['new_email']); if ($try !== true) { $errors[] = $try; } ... if
User
类,当他们登录时,他们的所有属性(权限、用户名、真实姓名等)都保存为类属性。但是,由于所有数据都需要验证,因此我很难集中精力思考让用户更新自己信息的最佳方法
目前,当用户尝试更新其自己的信息(例如其电子邮件地址)时,我会:
// Set new email
$try = $user->setEmail($_POST['new_email']);
if ($try !== true) {
$errors[] = $try;
}
...
if (isset($errors) {
// Tell user what went wrong
} else {
$user->saveValuesToDB();
}
它工作正常,但对我来说似乎相当难看,因为User->setEmail()
需要混合返回类型,因为电子邮件可能因多种原因(未找到域、格式无效、提供的空字符串、其他用户已使用等)而无效,确切原因需要传递回用户,但据我所知,一般不鼓励混合回报
我想到的另一种方法是更新所有属性,而不执行任何类型的验证,然后在最后执行User->commitAllChanges()
,这将执行所有验证,这将从所有setter方法中获取多个返回,并将其简化为仅提交方法,但我也不喜欢这样,因为我觉得任何实际设置的属性都应该是有效的,而且它仍然不能完全解决这个问题
我可以使用哪些其他方法来允许用户设置对象属性并验证它们,从而将错误发送回用户?或者说我现在做的很好吗?一种方法是保留您的解决方案(设置电子邮件功能)并使其更加面向对象。 在setAction中,您可以设置错误列表
$this->errors[] = 'Domain invaild';
然后使用1或2个函数从类中获取错误
public function hasErrors() {return false == empty($this->errors);}
public function getErrors() {return $this->errors;}
一种方法是保留您的解决方案(setEmail函数)并使其更加面向对象。 在setAction中,您可以设置错误列表
$this->errors[] = 'Domain invaild';
然后使用1或2个函数从类中获取错误
public function hasErrors() {return false == empty($this->errors);}
public function getErrors() {return $this->errors;}
当前方法没有问题,但可以使用异常 它可能看起来像:
try
{
$user->setEmail($_POST['new_email']);
}
catch (Exception $e)
{
$errors[] = $e->getMessage();
}
您的setEmail方法类似于:
setEmail($email)
{
if ($tooShort) // validate length
throw new Exception("Email is too short"); // perhaps have custom exceptions
}
当前方法没有问题,但可以使用异常 它可能看起来像:
try
{
$user->setEmail($_POST['new_email']);
}
catch (Exception $e)
{
$errors[] = $e->getMessage();
}
您的setEmail方法类似于:
setEmail($email)
{
if ($tooShort) // validate length
throw new Exception("Email is too short"); // perhaps have custom exceptions
}
我想到的另一种方法就是更新所有的
属性,而不执行任何类型的验证,然后执行
用户->commitAllChanges()将执行所有
验证,这将从所有
setter方法,并将其简化为仅提交方法
这通常是一个好方法。你也可以把整个过程分解成更小的部分,这样就更通用了
例如,模型可能有一个validate
方法返回一个布尔值(一切正常吗,还是有一个或多个错误?),还有一个getValidationErrors
方法返回一个数组,该数组包含您关心的所有信息(可能需要是多维的)。它可以有一个commit
方法,该方法自动调用validate
,并且只有在完全没有错误的情况下才会持久化更改
但我也不喜欢这样,因为我觉得
事实上,设置应该是有效的,但它仍然没有完全实现
摆脱这个问题
“无法设置”的属性比人们最初想象的要麻烦得多。主要的问题是,如果属性反对设置(通过返回一些错误代码,或者更好的是通过抛出异常),那么您必须用“保护”代码包装对它的所有访问。这很快就会变得非常乏味
在实践中,更方便的做法是通过一个helper方法为所有属性大规模赋值,然后查看结果(例如,如上所述调用validate
方法)
另外,不要忘记,在实践中,您可能希望在数据输入字段旁边显示验证错误,并且这些字段被连接为预先填充模型属性的值。因此,一方面属性需要有效,另一方面,它们需要与用户输入的内容完全匹配(否则用户会想要杀死你)。因此,最好放松“必须始终有效”的约束,以支持实用程序——尽管现在到处都是AJAX表单和客户端验证,这一点变得不那么重要了
我想到的另一种方法就是更新所有的
属性,而不执行任何类型的验证,然后执行
用户->commitAllChanges()将执行所有
验证,这将从所有
setter方法,并将其简化为仅提交方法
这通常是一个好方法。你也可以把整个过程分解成更小的部分,这样就更通用了
例如,模型可能有一个validate
方法返回一个布尔值(一切正常吗,还是有一个或多个错误?),还有一个getValidationErrors
方法返回一个数组,该数组包含您关心的所有信息(可能需要是多维的)。它可以有一个commit
方法,该方法自动调用validate
,并且只有在完全没有错误的情况下才会持久化更改
但我也不喜欢这样,因为我觉得
事实上,设置应该是有效的,但它仍然没有完全实现
摆脱这个问题
“无法设置”的属性比人们最初想象的要麻烦得多。主要的问题是,如果属性反对设置(通过返回一些错误代码,或者更好的是通过抛出异常),那么