【问题标题】:optimising php validator to OOP将 php 验证器优化为 OOP
【发布时间】:2012-01-30 14:52:51
【问题描述】:

我需要一个 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";
    }
}
}

问题在于,它甚至不考虑已注册用户名的数据库连接,

也是密码不匹配

我现在刚刚遇到了程序员的障碍,它在内部摧毁了我:(

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

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

非常感谢互联网人!

【问题讨论】:

  • 你看过现有的图书馆是如何做到的吗? Symfony Components 和 Zend Framework 都有很好的解决方案。它们比您这里的要大,但也涵盖更多案例。
  • 完全同意 Louis-Philippe 的观点,Zend Framework 具有完整的验证框架和易于理解的可扩展框架。我敦促您考虑使用此类框架,而不是自己制作。
  • 我认为这是一种自我教育。以防万一了解它如何工作,而不仅仅是使用它。

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


【解决方案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(),其中在选项 switchdefault 语句中放入 parent::validateOption()。所以指定的选项在新类中验证,旧的在基本验证器类中验证。

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

【讨论】:

  • 我最后没有使用这个实现,但是感谢您的回复
猜你喜欢
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
相关资源
最近更新 更多