优化php验证器到OOP

时间:2012-01-30 14:52:51

标签: php oop validation design-patterns strategy-pattern

我需要一个验证用户输入的php验证器类。

我希望它能够接受一个关联的数组字段=>值如:

array(
    "username" => "Alex",
    "email_address" => "@@#3423£alex@my.mail.com"
);

然后返回一个像这样的错误数组:

array(
    "username" => "",
    "email_address" => "Invalid Email Address"
);

但我真的在挣扎,我该怎么做呢!

我已经在PHP验证器上阅读了无数页面,并且读到最好的方法是使用策略模式。但我不知道怎么做?

喜欢......这就是我到目前为止所做的:

class Validator {

private
$_errors,
$_fields,

static private $_map = array (
    "firstname" => "name",
    "surname" => "name",
    "agency_name" => "name",
    "agency_office" => "name",
    "username" => "username",
    "email_address" => "email_address",
);
public function __construct( array $fields ) {
    $this->_fields = $fields;
}
public function validate() {
    foreach ( $this->_fields as $field => $value ) {
        if ( method_exists( __CLASS__, self::$_map[$field] ) ) {
            if ( in_array( $field, self::$_map ) ) {
                $this->{self::$_map[$field]}( $field, $value );
            }
        }
        else {
            die( " Unable to validate field $field" );
        }
    }
}
public function get_errors() {
    return $this->_errors;
}
private function name( $field, $value ) {
    if ( !preg_match( "/^[a-zA-Z]{2,50}$/", $value ) ) {
        $this->errors[$field] = "Invalid. Must be 2 to 50 alphanumerical characters";
    }
}
private function username( $field, $value ) {
    if ( !preg_match( "/^[a-zA-Z0-9_\-]{10,50}$/", $value ) ) {
        $this->errors[$field] = "Invalid. Must be 10 to 50 characters. Can contain digits, characters, _ (underscore) and - (hyphen)";
    }
}
private function password( $field, $value ) {
    if ( !preg_match( "/^[a-zA-Z0-9\.\-]{8,30}$/", $value ) ) {
        $this->_errors[$field] = "Invalid. Must be 8 to 30 characters. Can contain digits, characters, . (full stop) and - (hyphen)";
    }
}
private function email_address( $field, $value ) {
    if ( !filter_var( $value, FILTER_VALIDATE_EMAIL ) ) {
        $this->_errors[$field] = "Invalid Email Address";
    }
}
}

问题在于,它甚至没有考虑类似已经注册的用户名的数据库连接,

也是不匹配的密码

我刚刚让编码员阻挡它并在内部摧毁我:(

任何人都可以解释所需的课程和每个班级需要做的功能吗?

我确实需要输入和输出采用已经解释过的格式!

非常感谢互联网用户!

1 个答案:

答案 0 :(得分:1)

作为我MVC的一部分,我解决了同样的问题。我可以给你一个列表,但在几行中试着描述如何。

我有3个基类FormValidatorField,这些类的每个对象都通过一个YAML文件进行配置,结构如下:

name: // field name
  i18n:             [ ru, en ] // is the field i18n
  field:
    class:          Base // class to use for field
    options:        { specific_save: true } // options from available (defined in class)
    attributes:     { } // attributes, for HTML rendering
  validator:
    class:          String // Class to validate with
    options:        { required: true, max: 100 } // options for validator

所以,让我们从Form开始,当对象构建表单时,采用上面描述的YAML文件,并且由于该配置创建了字段。像这样:

// Imlement this function to configure form;
foreach ($this->_config as $f => $c)
{
    $class = '\\Lighty\\Form\\Field\\' . (isset($c['field']['class']) && $c['field']['class'] ? $c['field']['class'] : 'Base');
    $o = isset($c['field']['options']) && is_array($c['field']['options']) ? $c['field']['options'] : array();
    $a = isset($c['field']['attributes']) && is_array($c['field']['attributes']) ? $c['field']['attributes'] : array();
    $field = new $class($this, $o, $a);
    $field->setName($f);

    $class = '\\Lighty\\Form\\Validator\\' . (isset($c['validator']['class']) && $c['validator']['class'] ? $c['validator']['class'] : 'Base');
    $o = isset($c['validator']['options']) && is_array($c['validator']['options']) ? $c['validator']['options'] : array();
    $m = isset($c['validator']['messages']) && is_array($c['validator']['messages']) ? $c['validator']['messages'] : array();
    $field->setValidator($validator = new $class($field, $o, $m));

    if (isset($this->_options['default'][$f]))
    {
        $field->setValue($this->_options['default'][$f]);
    }

    if (isset($c['i18n']))
    {
        if (is_array($c['i18n']))
        {
            $field->setCultures($c['i18n']);
        }
        $field->setI18n((bool) $c['i18n']);
    }

    $this->addField($field);

所以,现在我们为每个字段创建了包含字段和验证器的表单,然后验证我是否使用了这个机制:

表单遍历每个字段,调用validate()方法, 字段(获取绑定值)调用绑定的Validator的validate($value)方法,传递存储的值。在此方法内部,Validator调用validateOption()方法,其中每个选项都有一个简单的开关,例如:

switch ($o)
{
    case 'required':
        $valid = $state && trim($value) != '' || !$state;
        break;
    default:
        return \warning(sprintf('Undefined validator option "%s" in %s validator class', $o, get_class($this->getField()->getValidator())), null);
}

您可以在此处查看所需选项的验证。如果我需要更多验证器,我会扩展Base验证器的类,定义更多选项,并重新定义validateOption(),在default选项switch放置parent::validateOption()的{​​{1}}语句中。因此,指定的选项在新类中验证,在基本验证器类中验证旧的。

如果有任何问题......欢迎您。