2010-05-17 34 views
1

从表单提交中处理数据验证的有效方法是什么?有效数据验证

最初我有一堆if语句检查每个值并收集数组中的无效值以便以后检索(和列表)。

// Store errors here 
$errors = array(); 

// Hypothetical check if a string is alphanumeric 
if (!preg_match('/^[a-z\d]+$/i', $fieldvalue)) 
{ 
    $errors[$fieldname] = 'Please only use letters and numbers for your street address'; 
} 

// etc... 

接下来我做了什么是创建一个类来处理各种数据验证场景并将结果存储在内部数组中。数据验证完成后我会检查,看看是否发生了任何错误,并进行相应处理:

class Validation 
{ 
    private $errorList = array(); 

    public function isAlphaNumeric($string, $field, $msg = '') 
    { 
     if (!preg_match('/^[a-z\d]+$/i', $string)) 
     { 
      $this->errorList[$field] = $msg; 
     } 
    } 

    // more methods here 

    public function creditCard($cardNumber, $field, $msg = '') 
    { 
     // Validate credit card number 
    } 

    // more methods here 

    public function hasErrors() 
    { 
     return count($this->errorList); 
    } 
} 

/* Client code */ 

$validate = new Validation(); 
$validate->isAlphaNumeric($fieldvalue1, $fieldname1, 'Please only use letters and numbers for your street address'); 
$validate->creditCard($fieldvalue2, $fieldname2, 'Please enter a valid credit card number'); 

if ($validate->hasErrors()) 
{ 
    // Handle as appropriate 
} 

自然,没多久之前,该类成为臃肿与几乎无限类型的数据进行验证。我现在正在做的是用装饰不同类型的数据到自己的类,需要留下的通用验证,只有当打电话给他们(即isAlphaNumeric())在基类:

class Validation 
{ 
    private $errorList = array(); 

    public function isAlphaNumeric($string, $field, $msg = '') 
    { 
     if (!preg_match('/^[a-z\d]+$/i', $string)) 
     { 
      $this->errorList[$field] = $msg; 
     } 
    } 

    // more generic methods here 

    public function setError($field, $msg = '') 
    { 
     $this->errorList[$field] = $msg; 
    } 

    public function hasErrors() 
    { 
     return count($this->errorList); 
    } 
} 

class ValidationCreditCard 
{ 
    protected $validate; 

    public function __construct(Validation $validate) 
    { 
     $this->validate = $validate; 
    } 

    public function creditCard($cardNumber, $field, $msg = '') 
    { 
     // Do validation 
     // ... 
     // if there is an error 
     $this->validate->setError($field, $msg); 
    } 

    // more methods here 
} 

/* Client code */ 

$validate = new Validation(); 
$validate->isAlphaNumeric($fieldvalue, $fieldname, 'Please only use letters and numbers for your street address'); 

$validateCC = new ValidationCreditCard($validate); 
$validateCC->creditCard($fieldvalue2, $fieldname2, 'Please enter a valid credit card number'); 

if ($validate->hasErrors()) 
{ 
    // Handle as appropriate 
} 

我是上正确的轨道?或者我只是把数据验证复杂化了,然后我需要呢?

+0

我还使用了您在上描述的一样。我也有兴趣得到这个问题的答案。 Currenlty也是我验证一个表格。我使用TryParse和其他可能的inbuild函数。剩下我创造自己。 – 2010-05-17 11:53:03

回答

2

如果有的话,你没有足够的验证。对于在$ _ POST数据读取和$ _GET,你至少需要:

  • 要检查它是否存在(array_key_exists)
  • 要检查它是否是一个数组或不
  • 如果希望UTF-8,检查是否它是有效的UTF-8(的preg_match与“U”修饰符是一个选项)
  • 然后做具体到现场

的类型验证顺便说一句,目前的臀部的方式做验证和消毒的PHP是使用filters。在特定情况下,这里有一个例子:

<?php 
$data = array(
    "arg1good" => "sdgdf790", 
    "arg1bad" => "sdgdf7/90", 
    "arg1bad2" => array("sdgdf90", "sfdssf"), 
    "arg2good" => "4567576456", 
    "arg2bad" => "45675764561", 
); 

$validateCredCard = function ($cc) { 
    if (preg_match('/^\\d{10}$/', $cc)) 
     return $cc; 
    else 
     return false; 
}; 

$arg1filt = array('filter' => FILTER_VALIDATE_REGEXP, 
        'flags' => FILTER_REQUIRE_SCALAR, 
        'options' => array('regexp' => '/^[a-z\d]+$/i'), 
       ); 
$arg2filt = array('filter' => FILTER_CALLBACK, 
        'flags' => FILTER_REQUIRE_SCALAR, 
        'options' => $validateCredCard, 
       ); 
$args = array(
    "arg1good" => $arg1filt, 
    "arg1bad" => $arg1filt, 
    "arg1bad2" => $arg1filt, 
    "arg2good" => $arg2filt, 
    "arg2bad" => $arg2filt, 
); 

var_dump(filter_var_array($data, $args)); 

给出:

array(5) { 
    ["arg1good"]=> 
    string(8) "sdgdf790" 
    ["arg1bad"]=> 
    bool(false) 
    ["arg1bad2"]=> 
    bool(false) 
    ["arg2good"]=> 
    string(10) "4567576456" 
    ["arg2bad"]=> 
    bool(false) 
} 
0

这对我来说似乎过于复杂。

数值数据:只投了$ _ POST值

$val=(int)$_POST["val"]; 

电子邮件:有一些做的(希望找到一个正确的)预制功能。

$email=check_email($_POST["email"]) or die("Ha!"); 

名称和地址:什么也不做,因为它会是一个陌生人进入你也没有多想和你的功能被过滤掉一个Unicode字符的一天。

电话号码:什么都不做,如果他想给一个错误的号码,他会这样做。

特殊代码,如邮政编码和类似的东西:你通常会有一个非常严格的标准,创建一个函数,使用该函数进行过滤并完成。

1

你好像并不被你的目标非常明确 - 性能?新代码的简单性?整体可维护性?

当然,出于性能方面的原因,我建议将验证保存为代码而不是将正则表达式(以及阈值和....)作为数据存储。问题似乎是你如何将数据项映射到适当的验证。虽然可以将静态映射设置为数组,但由于您还需要了解有关数据结构的某些信息以呈现表单并映射到数据库列,因此您可能应该考虑在代码中实施更为正式的元数据管理方法。

C.

0

@ Lo'oris 你关于铸造的价值观并不完全完整的答案。请考虑下面的例子:

$val_1 = (int)null; // $val_1 equals 0 
$val_2 = (int)false; // $val_2 equals 0 
$val_3 = (int)'';  // $val_3 equals 0 
$val_4 = (int)array(); // $val_4 equals 0 

正如这个例子正显示出,如果你希望该变量是一个整数,是该战略只适用大于0

在“check_email方面“功能 - 你在网上可以找到许多实现是正确的,但其中大部分都是不完整或不正确的。

大多数实现使用正则表达式的表达式像这样的:

"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$" 

或者这一个:

"^[a-zA-Z0-9_.-][email protected][a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$" 

和这两个正则表达式拒绝的电子邮件地址类似这样:

Abc\@[email protected] 
customer/[email protected] 
!def!xyz%[email protected] 

其中全部有效(根据http://www.linuxjournal.com/article/9585?page=0,0)。

也请看看: http://www.regular-expressions.info/email.html

+0

我不明白你对铸造的观点:是的,那些不正确的值将被转换为0 ......对我来说很好!如果“你”需要更严格的东西,比如> 0,那么就说出来,只是编码,这不是那种需要解释的奇特的东西...... – 2010-09-23 11:26:36