Log*_*man 8 php validation error-handling
只要我一直在开发Web应用程序,我一直在寻找更好的方法来处理验证.通常需要捕获多个验证错误,因此我想知道是否有比下面更好的方法.
现在我assert
在自己开发的框架中有一个方法.方法的一个例子是:
assert(($foo == 1), 'Foo is not equal to 1');
如果第一个参数中的条件为false,则将第二个参数中的错误消息添加到$errors
数组中(该数组包含在$eh
提供便利函数的类中(由下面引用)hasErrors()
).
这种方法有效,但在实践中很麻烦.考虑以下代码:
public function submit($foo, $bar, $baz)
{
assert(($foo == 1), 'Foo is not equal to 1');
assert(($bar == 2), 'Bar is not equal to 2');
if (!$eh->hasErrors())
{
assert(($baz == 3), 'Baz is not equal to 3');
if (!$eh->hasErrors())
{
finallyDoSomething();
return;
}
}
outputErrors();
}
Run Code Online (Sandbox Code Playgroud)
这是相当普遍的事情.我想在继续之前检查两个条件,然后如果这些条件通过,请在最终做我想做的事之前检查第三个条件.如您所见,此代码中的大多数行都与验证有关.在实际的应用程序中,将有更多的验证和可能更多嵌套的if语句.
有没有人有比这更好的处理验证结构?如果有更优雅地处理这个问题的框架,那么它们是什么以及它们如何实现呢?多个嵌套的if语句似乎是解决问题的"强力"解决方案.
只是一个注释,我理解在一个类中包含一些常见的验证函数可能是个好主意,这样我就可以通过调用这些函数来检查长度,字符串格式等.我要问的是一种更清晰的代码结构方法,而不是我实际检查错误的方法.
谢谢!
请检查Respect\Validation.这是一个为那个purpouse而建的图书馆.它可以非常轻松地处理多个规则并使用异常来处理错误.这是一个快速示例:
<?php
use Respect\Validation\Validator as v;
$usernameValidator = v::alnum()->noWhitespace()->length(1,15);
$valid = $usernameValidator->validate("alganet"); //$valid now == true
$valid = $usernameValidator->validate("ácido acético"); //$valid now == false
Run Code Online (Sandbox Code Playgroud)
现在使用例外:
try {
$usernameValidator->assert("foo # bar");
} catch (Exception $e) {
$errors = $e->findMessages('alnum', 'noWhitespace', 'length');
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,$errors
变量将是这样的:
array(
"alnum" => '"foo # bar" must contain only letters and digits',
"noWhitespace" => '"foo # bar" must not contain whitespace',
"length" => null
)
Run Code Online (Sandbox Code Playgroud)
我使用"foo #bar"打破了两个先前声明的规则:它有空格,并且它有一个非alnum char.对于每个未通过的规则,将返回一条消息.由于"长度"正常,因此错误消息为空.
该文档包括几个样本,包括嵌套的分层规则和更好的异常处理.还有30多个内置验证器的广泛样本列表.
希望有所帮助!
抛出异常怎么样?您可以使用 try /catch 块显式捕获异常,和/或使用以下方法捕获它们set_exception_handler()
PHP 中定义了许多有用的异常类型,如果您需要异常处理的粒度,可以使用它们来发挥自己的优势。另外您还可以定义自定义异常。
http://php.net/manual/en/function.set-exception-handler.php http://www.php.net/manual/en/spl.exceptions.php
编辑
要回答有关其他一些框架如何解决此问题的问题 - 明智地使用异常似乎很常见。使用它们的有用之处在于,假设您有一个特定的方法,它执行了许多可能是错误的不同验证 - 您可以在每种情况下抛出适当的异常,但您不必处理不同的可能异常那个方法。相反,根据您构建代码的方式,您可以允许异常冒泡到代码中更集中的位置,您可以在其中捕获它并进行适当的处理。
编辑2
详细说明我最后的评论filter_input_array()
基于一个非常简单的示例,其中包含已发布的用户数据。首先创建一个定义:
$userFormDefinition = array(
'email' => FILTER_VALIDATE_EMAIL,
'age' => FILTER_VALIDATE_INT,
'name' => array(
'filter' => FILTER_VALIDATE_REGEXP,
'options' => array('regexp' => '/^\w+$/')
),
);
Run Code Online (Sandbox Code Playgroud)
然后使用通用验证类(类定义如下):
$formValidator = new FormValidator();
$formValidator->validatePost($userFormDefinition);
if ($formValidator->isValid()) {
// if valid, retrieve the array
// and use the values how you wish
$values = $formValidator->getValues();
// for example, extract and populate
// a User object, or whatever :)
extract($values);
$user = new User();
$user->setName($name);
$user->setEmail($email);
$user->setAge($age);
// etc.
}
Run Code Online (Sandbox Code Playgroud)
FormValidator 的一个非常基本(且未经测试)的实现。
基本用例是调用适当的方法来过滤请求方法。这反过来会检查返回的值并决定输入是否有效。
这可能需要大量的爱 -尤其是方法filterInput
,因为您可能需要进行一些测试以确保正确处理“真实”或“虚假”值。我正在考虑复选框类型值。直接in_array
检查false
可能不会像这里实现的那样削减它。但是您可以通过定义传递大量标志。
我想您还可以通过比较结果数组和定义的计数来检查丢失的输入$values
,以确保它们匹配。定义中未包含的其他输入将被过滤掉(您可能想检查这一点,但我相当确定这一点)。
<?php
class FormValidator
{
private $isValid = false;
private $isBound = false;
private $values = array();
public function validatePost(array $definition)
{
// additional REQUEST_METHOD checking here?
$this->filter(INPUT_POST, $definition);
}
public function validateGet(array $definition)
{
// additional REQUEST_METHOD checking here?
$this->filterInput(INPUT_GET, $definition);
}
protected function filterInput($type, $definition)
{
$this->isBound = true;
$this->values = filter_input_array($type, $definition);
// might have to do some reading on nulls vs false,
// and validating checkbox type values here... you can
// set all sorts of flags so a better implementation
// would probably be required here... :s
if (is_array($this->values) && !in_array(false, $this->values))) {
$this->isValid = true;
}
}
public function isValid()
{
if (!$this->isBound) {
throw new Exception("you didn't validate yet!");
}
return $this->isValid;
}
public function getValues()
{
if (!$this->isBound) {
throw new Exception("You didn't validate yet!");
}
return $this->values;
}
}
Run Code Online (Sandbox Code Playgroud)
无论如何,我会说重构并测试该类中的 bejayzis(甚至完全更改它),但希望它概述了基本思想:对于每种类型的输入,创建一个定义,然后使用通用验证类来过滤并确保有效性。
希望这可以帮助。filter_input
和filter_input_array
摇滚:)
归档时间: |
|
查看次数: |
3971 次 |
最近记录: |