Etkin Veri Doğrulama

4 Cevap php

Bir form gönderme veri doğrulama, diyelim ki, işlemek için etkili bir yol nedir?

Aslında ben daha sonra geri alma (ve liste) bir dizinin her bir değeri ve toplanan geçersiz değerleri kontrol if tabloların bir grup vardı.

// 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...

Ne sonraki yaptım, çeşitli veri doğrulama senaryoları işleyen bir sınıf oluşturmak ve bir iç dizide sonuçlar saklamak oldu. Veri doğrulama tamamlandıktan sonra herhangi bir hata oluşup oluşmadığını görmek için kontrol edin ve buna göre işlemek:

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
}

Bu sınıf valide edilecek verilerin neredeyse sınırsız türleri ile şişirilmiş olmadan önce doğal olarak uzun sürmedi. Ben şimdi ne yapıyorum kendi sınıflarının içine veri farklı ayrı ve temel sınıfta jenerik doğrulamaları (yani isAlphaNumeric ()) bırakarak yalnızca gerektiğinde onları aramak için dekoratörler kullanıyor:

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
}

Ben doğru yolda mıyım? Ya ben sadece gerekiyordu daha sonra veri doğrulama zorlaştırmak mı?

4 Cevap

Eğer bir şey, yeterince doğrulayarak değil. $ _POST Ve $ _GET okuma verileri için en az gerekir:

  • Bunun var olup olmadığını kontrol etmek için (array_key_exists)
  • Bir dizi ya da değil olup olmadığını kontrol etmek için
  • UTF-8, geçerli UTF-8 olup olmadığını kontrol bekliyor ('u' değiştirici ile preg_match bir seçenek ise)
  • Daha sonra alanın tipine özgü doğrulama yapmak

Bu arada, PHP doğrulama ve sanitasyon yapmak için geçerli kalça yolu kullanmaktır filters. Özel durumda, burada bir örnek:

<?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));

verir:

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

Performans - Sen hedefleri ne hakkında çok açık gibi görünüyor değil mi? Yeni kod basitliği? Genel idame?

Elbette, performans nedenleriyle ben veri olarak (.... ve eşikleri, ve) kod olarak doğrulamaları muhafaza ziyade Regexes depolama öneririm. Sorun, uygun doğrulamaları için sahip veri öğeleri haritası gibi görünüyor. Ayrıca formları işlemek ve veri tabanı sütunları eşleştirmek için veri yapısı hakkında bir şeyler bilmek gerek bu yana, bir dizi olarak statik bir harita kurmak olsa da, belki sizin kodu içinde meta-veri yönetimi bir daha resmi yöntemi uygulayan düşünmelisiniz .

C.

Bu benim için aşırı karmaşık görünüyor.

Sayısal veriler: sadece $ _POST değerini cast

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

E-postalar: (a doğru olanı bulmak için umut) anlamına Premade fonksiyonlar vardır.

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

İsimler ve adresler: bir yabancı hakkında düşünmüyordu ve işlevi tarafından filtre edilebilir bir unicode karakter girer gün gelecek bu yana, hiçbir şey.

Telefon numaraları: o zaten yapacak bir yanlış numara vermek isterse, hiçbir şey yapmak.

Örneğin post kodu ve bunun gibi şeyler gibi özel kodları: genellikle, çok sıkı bir standardı var filtre bir ve bitirdiniz o kullanarak bir işlev oluşturmak olacak.

@Lo'oris Your answer regarding casting the values is not entirely complete. Please consider the following example:

$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

Bu örnek gösteriyor gibi, bu strateji değişken 0'dan also büyük bir tamsayı olmasını sadece çalışır.

"Check_email" fonksiyonları açısından - Orada internette bulunabilecek birçok uygulamaları vardır, ama çoğu eksik veya yanlış ya vardır ki haklısınız.

Uygulamaların çoğu bu gibi regex ifadeleri kullanabilirsiniz:

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

ya da bu bir:

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

ve hem o regexes bu gibi e-posta adresleri reddetmek:

Abc\@def@example.com
customer/department=shipping@example.com
!def!xyz%abc@example.com 

all geçerli göre (http://www.linuxjournal.com/article/9585?page=0,0) olan.

Please also have a look at: http://www.regular-expressions.info/email.html