2010-05-17 3 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 
} 

Am I на правильный трек? Или я просто усложнил проверку данных больше, чем мне нужно?

+0

Я также использует тот же способ, вы описали в прошлом. Я также был бы заинтересован в получении ответа от этого Ques. Currenlty также проверяет форму. Я использую TryParse и другие встроенные функции, до которых это возможно. Оставшаяся я создаю себя. –

ответ

2

Во всяком случае, вы недостаточно проверяете. Для чтения данных в $ _POST и $ _GET вам нужно как минимум:

  • Чтобы проверить, существует ли она (array_key_exists)
  • Чтобы проверить, является ли это массив или нет
  • Если ожидает UTF-8, проверьте она действует UTF-8 (preg_match с «и» модификатор опции)
  • Затем сделать проверку, специфичную для типа поля

Кстати, нынешний способ бедра сделать проверку и дезинфекцию в 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"]; 

сообщения электронной почты: есть Premade функции, которые делают, что (надеюсь найти правильный).

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

Имена и адреса: ничего не делать, так как он придет тот день, когда незнакомец входит в юникод символ, который вы не думали о том и быть отфильтрованы вашей функции.

Телефоны: ничего не делать, если он хочет дать ложное число, он все равно это сделает.

Специальные коды, такие как почтовый индекс и тому подобное: у вас обычно будет очень строгий стандарт, создайте функцию, которая будет фильтровать с помощью этого, и все готово.

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, ну, просто скажите, что и просто код, это не то, что нужно объяснить экзотике ... –

Смежные вопросы