2010-05-17 37 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