【问题标题】:Structure of a form validation class表单验证类的结构
【发布时间】:2011-06-09 06:16:33
【问题描述】:

我想在 OOP PHP 中创建一个类来验证表单。但是,我在构建这个时遇到了麻烦。 最初我想为每种类型的验证创建单独的函数(检查提交数据的长度,检查它是否是数字等),然后是另一个函数来检查数据是否通过了验证测试并将错误传递到数组中。 我被卡住了,因为我的代码变得很长并且难以管理 - 我很新,所以你会如何解决这个问题?

【问题讨论】:

  • 你能给我们看一些代码吗?您如何处理表单提交?您是如何打印表单的?
  • 你看过Zend_Validate吗?
  • @zerkms 我还没有看 Zend_validate,谢谢,我去看看
  • @alexn 呃,我一直在添加/删除代码并重做它——基本上我试图创建一个具有多个执行各种验证方法的函数的类。我在顶部调用了类和函数,并有表单自我引用,但我真的不知道从这里去哪里。 ..
  • @Janee 这是我个人使用的验证脚本的简化版本pastebin.com/svZXreyS。希望它能给你一些想法。

标签: php oop validation forms


【解决方案1】:

当我阅读您的帖子时,我想到了一个关于您所写内容的问题:

为什么不验证表单,而不验证模型的对象? 我的意思是,以 OOP 的方式看待事物,您的模型对象(或域对象)是那些知道哪些数据对其每个属性有效或无效的对象。 不要那样做,将这种逻辑推入 UI 会使您的设计变得脆弱、依赖于 UI 并且更难维护。如果您向模型的一个对象添加新属性,您还必须修改表单验证器。

如果您使用对象验证,其想法是不能在无效状态下创建对象。如果您尝试使用无效数据对其进行修改,则会引发异常。 这使得使用表单变得容易。您唯一需要做的就是填充您的对象并注意该过程中引发的异常。 这只是让您开始并了解解决此问题的另一种方法的想法。

关于您关于表单验证的问题,正如其他人所说,最好不要重新发明轮子并使用现有的、经过验证的验证框架。

但是,如果您对此感到好奇,这里是众多方法之一您可以做到这一点:

让我们来看看你需要的东西:你正在谈论一个需要验证的表单具有一个或多个验证函数。然后你谈论一个函数,它告诉你表单是否通过了验证,结果你得到了在过程中发现的错误列表验证阶段。

当您谈论 OOP 时,要走的路是通过一个代表问题域(表单验证域)实体的每个概念或想法,通过一个类来模拟它们的行为。

因此,很自然地想到一个带有ValidationRule 实例列表的FormValidator 类,每个实例都在验证过程中协作。这个验证过程是通过调用FormValidator 的validate 函数来完成的。此外,每个ValidationRule 都会在调用它自己的validate 方法时给出ValidationRuleResult 类的实例,该实例告诉验证是否成功,以及错误消息和附加数据(如果需要)关于验证。评估完所有验证规则后,FormValidator 类的 validate 方法将返回 ValidationResult 类的实例,该实例汇总了评估规则的所有验证结果,并提供了找到的错误列表。

为了切实做到这一点,以下是我们正在讨论的示例模型:

示例实现

免责声明:请记住,与任何设计一样,它可能包含缺陷。以下内容旨在帮助您解决问题,而不是完整的解决方案。

class FormValidator {
    private $_validationRules;

    function __construct() {
            $this->_validationRules = array();
    }

    // Registers a new validation rule
    function addRule($aValidationRule) { $this->validationRules[] = $aValidationRule; }

    // Validates $aForm, evaluating each of the $_validationRules defined
    function validate($aForm) {
            $aValidationResult = new ValidationResult();

            foreach($this->_validationRules as $aValidationRule) {
                    $aValidationRuleResult = $aValidationRule->validate($aForm);
                    $aValidationResult->addResult($aValidationRuleResult);
            }

            return $aValidationResult;
    }
}

abstract class ValidationRule {
    private $_fieldName;

    // The form's field name to be validated
    function __construct($aFieldName) {
            $this->_fieldName = $aFieldName;
    }

    function fieldName() { return $this->_fieldName; }

    // Returns an instance of ValidationResult describing the result of evaluating the ValidationRule in $aForm.
    abstract public function validate($aForm);
}

class ValidationResult {
    private $_validationRuleResults;

    function __construct() {
            $this->_validationRuleResults = array();
    }

    // Registers a validation rule result
    function addResult($aValidationRuleResult) {
            $this->_validationRuleResults[] = $aValidationRuleResult;
    }

    // Returns the list of the error messages of the validation rule results that did't passed
    function errorsFound() {
            $errors = array();

            foreach($this->validationRuleResults as $aValidationResult) {
                    if ($aValidationResult->passed()) continue;
                    $errors[] = $aValidationResult->errorMessage();
            }

            return $errors;
    }

    // Tells whether all the validation rule results passed or not
    function validationPassed() {
            foreach($this->validationRuleResults as $validationResult) {
                    if ($validationResult->passed() == false) return false;
            }

            return true;
    }
}

class ValidationRuleResult {
    private $_passed, $_error_message;

    function __construct($passed) {
            $this->_passed = $passed;
            $this->_error_message = '';
    }

    // Tells whether the form passed this validation rule or not
    public function passed() { return $this->_passed; }
    public function

    // The error message should be empty if passed to avoid confusion
    public function errorMessage { return $this->passed() ? '' : $this->_error_message; }
    public function setErrorMessage($anErrorMessage) { $this->_error_message = $anErrorMessage; }
}

您可以通过这种方式创建验证规则:

class NotEmptyValidationRule extends ValidationRule {
    public function validate($aForm) {
            $fieldName = $this->fieldName();
            $fieldValue = $aForm[$fieldName];

            $passed = !empty($fieldValue);
            $result = new ValidationRuleResult($passed);

            if (!$passed) {
                    $result->setErrorMessage("$fieldName cannot be empty");
            }

            return $result;
    }
}

注意事项:

  • 我假设 $aForm 是字段名称/值的关联数组
  • 您可以注意到,如果验证规则通过,则不会使用结果(因为ValidationResult 类仅适用于未通过的结果)。请记住,这只是一个示例,仅用于帮助您,并非完整的解决方案。

用法

 $rule = new NotEmptyValidationRule('name');
 $validator = new FormValidator();
 $validator->addRule($rule);

 $aForm = $__POST['myForm'];
 $validationResult = $validator->validate($aForm);

if ($validationResult->validationPassed()) {
    $errorsFound = $validationResult->errorsFound();
    // do something with the $errorMessage
    $errorMessage = array_join('<br/>', $errorsFound);        
}

【讨论】:

  • 嘿- 刚刚回到这个问题,看到了这个非常详细的答案。感谢您抽出宝贵时间 - 非常有帮助。
  • @Janee,不客气 :) 很高兴它对您有所帮助。干杯!
  • 另一个 +1。在这里的辛勤工作很少得到其他人应有的赞赏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多