将php验证器优化为面向对象


optimising php validator to OOP

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

我希望它能够接受一个由字段=>值组成的assoc数组,比如:

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";
    }
}
}

问题是,它甚至没有考虑数据库连接,例如,已经注册的用户名,

也是不匹配密码

我现在刚刚遇到了编码器阻塞,它在内部摧毁了我:(

有人能解释一下每个类需要做的类和函数吗?

我真的需要输入和输出的格式已经解释过了!

非常感谢互联网人!

作为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);

因此,现在我们有了带有字段和每个字段的验证器的表单,然后为了验证,我使用了以下机制:

Form遍历每个字段,调用validate()方法,Field(获取绑定值)调用绑定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(),其中在选项的switchdefault语句中放入parent::validateOption()。所以指定的选项在新的类中进行验证,旧的选项在基验证器类中进行。

如果有任何问题。。。不客气。