大型表单验证结构


Large form validation structure

我目前正在PHP中构建一个表单管理器来验证大型表单。

我想知道什么是最好的结构,因为字段的数量每次都会不同。

我已经通过使用前缀过滤字段来验证(例如:'user_name',将被验证,但'name'没有)。

我真正的问题是验证:我必须检查字段的类型(邮件,邮政编码,电话…)并检查此类型字段的值是否有效。

我以为我可以使用HTML5自定义数据"(例如:data-fieldtype="zipcode"),但我不知道服务器不能得到这个属性…

怎么走?

我可以为每个字段使用两个输入,一个用于值,一个用于类型,但它看起来真的很愚蠢!

如果你能帮忙的话,谢谢。

编辑:

你的答案都很有趣,我不知道哪个最好。我可能会把你的溶液混合起来,这取决于你的形式。

我认为,这不应该在没有进一步考虑的情况下通过浏览器进行:恶意用户将能够将"INT ONLY"字段操纵为freetext,并且您的应用程序将突然不得不处理字段中的freetext,这被认为是验证为整数(因此例如对SQL安全)。

有两种方法:

  • 将表单验证结构存储在DB中,并提交一个隐藏字段,该字段携带验证结构的ID。在接收到请求后,您的脚本将从DB请求该结构,对其进行反序列化,然后处理它。
  • 如果你真的需要通过浏览器,序列化你的验证结构,base64编码,并使用它作为一个单独的隐藏字段。由于上述原因,必须对该值进行身份验证,可以使用哈希(与服务器已知的另一个字符串连接,对其进行哈希,将哈希作为第二个隐藏字段发送,在下一次请求时验证哈希是否正确)或加密(在浏览器往返之前加密序列化数据,之后解密,密钥仅为服务器所知)
这两种方法都会使前缀技巧变得不必要,从而增加可读性和可维护性。

如果没有使用框架,可以使用field =>选项数组。

$rules = [
            'user_name' => 'required',
            'user_email' => 'email required',
           // ...
         ];

然后将它们提供给一些验证器类,其中规则是方法,并且它们在validate方法中动态调用:

class Validator {
   public function __construct($data) { $this->data = $data; }
   private function required($field) {}
   private function email($email) {}
   // etc
   /** @method bool validate(array $rules) */
   public function validate($rules) {}
}

永远不要只在客户端验证。

通常你会有一个控制器的基类,每个其他控制器都继承它。

一个好的方法是甚至每个视图控制器(或bootsrtap)都有一个方法check_params()。它应该1)获取$_REQUEST的副本,检查所需的每个参数,2)删除$_REQUEST, 3)回写检查过并验证过的参数。

abstract class controller_base {
    public function __construct() { ...; $this->check_param();...}
    protected final function check_param() {
        foreach ($this->param_list() AS $name => $type) {...}
    }
    abstract public function param_list();
}
class controller_login extends controller_base {
    public function param_list() {
        return array('name' => 'string', 'password' => 'string');
    }
}

这个想法是这样的

  • 只使用已消毒的参数
  • 自动删除所有不需要的参数
  • 在每个控制器中都有一个列表,说明使用的参数。