За последние 24 часа нас посетили 18076 программистов и 1651 робот. Сейчас ищут 1618 программистов ...

form validation [готовое решение, принимаются замечания]

Тема в разделе "Решения, алгоритмы", создана пользователем Koc, 15 фев 2009.

  1. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    2issa для расширения класса своими проверками, смотри ниже этого сообщения пример такого расширения.

    Я немного обновил класс. Пока что он мало тестировался и не все проверки еще работают (по коду видно, что site и ftp не работают)

    код помещен в репозиторий

    Как и обещал пример расширения класса своими проверками:

    код помещен в репозиторий

    Принимаются предложения к улучшению класса
     
  2. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
  3. kostyl

    kostyl Guest

    Psih
    а как это подключать во время выполнения, если хостер не может?


    А вообще по сабджекту, я делаю статический класс Request и он фильтрует мне все переменные, а не только одну форму....
     
  4. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    kostyl
    Сделать либу, которая при отсуствии filter на хостинге делает тоже самое
     
  5. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    зачем мне весь реквест фильтровать? мне конкретные поля нужны.

    про Filter только пару недель назад узнал, но мне все равно своим велосипедом удобней пользоваться.
     
  6. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Psih
    имхо, неудобная байда
     
  7. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Такая идея пришла. Почему бы не рассматривать валидатор как простую цепочку правил? Подумать над реализацией ещё конечно нужно, но, как мне кажется, такой вариант имеет право на существование.

    PHP:
    1. <?php
    2. $validator = Rule::chain()
    3.     ->add(
    4.         Rule::chain('login')
    5.             ->add(new NotEmptyRule())
    6.             ->add(new LengthRule(3, 30))
    7.             ->add(new IsEmailRule())
    8.     )
    9.     ->add(
    10.         Rule::chain('password')
    11.             ->add(new NotEmptyRule())
    12.             ->add(new LengthRule(3, 30))
    13.     )
    14.     ->add(
    15.         Rule::chain('some_key_arr')
    16.             ->add(new IsArrayRule())
    17.             ->add(
    18.                 Rule::chain('some_arr_key')
    19.                     ->add(new NotEmptyRule())
    20.                     ->add(new CallbackRule($some_object, 'customValidateMethod'))
    21.             )
    22.     );
    23.  
    24.  
    25. $_POST = array(
    26.     'login'        => 'dmitry',
    27.     'password'     => '',
    28.     'some_key_arr' => array(
    29.         'some_arr_key' => 'bla bla'
    30.     )
    31. );
    32.  
    33. if ($validator->validate($_POST)) {
    34.     // ...
    35. } else {
    36.     print_r($validator->getErrors());
    37. }
    38.  
     
  8. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    можно наверно. Но такое я врятли напишу в ближайшее время, так как его совсем нет =).
    Меня пугает такое кол-во создаваемых объектов.
     
  9. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Боятся надо не количества, а качества.
     
  10. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    э, а откуда транслит появился? Прикольно в этом году у вас на 1 апреля =)
     
  11. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Sergey89
    лучше так

    PHP:
    1.  
    2. <?
    3. class FormValidate {
    4.     public static $cnf=array(
    5.         "formvalidate_def_errors"=>array(
    6.                                    "noempty"=>"Поле {name} не должно быть пустым",
    7.                                    "regexp"=>"Поле {name} не соответсвует шаблону {type_value}",
    8.                                    "limitlength"=>"Поле {name} не может быть длиннее {type_value} символов",
    9.                                    "minlength"=>"Поле {name} не может быть короче {type_value} символов",
    10.                                    "int"=>"Поле {name} может быть только числом",
    11.                                    "noint"=>"Поле {name} не может содержать чисел",
    12.         ),
    13.         "formvalidate_allow_types"=>array("noempty","regexp","limitlength","mreplace","replace","minlength", "addslashes","stripslashes","escape","r_replace", "htmldecode","int","md5","nohtml","userfunc","noint"),
    14.         "formvalidate_method"=>"POST",
    15.     );
    16.     public $types=array();
    17.     function __construct($cnf=false){
    18.         if($cnf)self::$cnf=$cnf; else self::$cnf=locator::LoadData('config');
    19.     }
    20.     function SetType($name,$types=array()){
    21.         if(!is_array($name)){
    22.            $this->types[$name]=$types;
    23.         }else{
    24.            foreach($name as $key=>$val)
    25.                   $this->SetType($key,$val);
    26.         }
    27.     }
    28.     function SetMethod($type){
    29.         self::$cnf['formvalidate_method']=$type;
    30.     }
    31.     function CheckError(){
    32.         $errors=array();
    33.         if(!empty($this->types)){
    34.             foreach($this->types as $name=>$types){
    35.                    for($i=0,$c=count($types);$i<$c;$i++){
    36.                        if(is_array($types[$i])){
    37.                           $str=$types[$i][0];
    38.                           $msg=$types[$i][1];
    39.                        }else{
    40.                           $str=$types[$i];
    41.                           $msg=false;
    42.                        }
    43.                        $row=$this->TypeResources($str);
    44.                        if(in_array($row['name'],(array)self::$cnf['formvalidate_allow_types']) && method_exists($this,$method="Parse".$row['name'])){
    45.                           if($this->$method($name,$row)){
    46.                               if(!$msg){                                   
    47.                                  $errors[]=$this->ErrorTpl(strtolower($row['name']),array("name"=>$name,"type_value"=>$row['type_value']));
    48.                               }else{
    49.                                  $errors[]=$this->ErrorMsg($msg,array("name"=>$name,"type_value"=>$row['type_value']));
    50.                               }
    51.                           }
    52.                        }
    53.                   }
    54.             }
    55.         }
    56.         return $errors;
    57.     }
    58.     private function TypeResources($str){
    59.         preg_match("#^([\w]+)(?:\[(.+)\])?$#i",$str,$res);
    60.         return array("name"=>strtolower($res[1]),"type_value"=>$res[2]);
    61.     }
    62.     private function VarGet($name){
    63.          switch(self::$cnf['formvalidate_method']){
    64.              case "GET":
    65.                 return $_GET[$name];
    66.              break;
    67.              case "REQUEST":
    68.                 return $_REQUEST[$name];
    69.              break;
    70.              default;
    71.                 return $_POST[$name];
    72.          }
    73.      }
    74.      private function VarSet($value){
    75.          switch(self::$cnf['formvalidate_method']){
    76.              case "GET":
    77.                 return $_GET=array_merge((array)$_GET,(array)$value);
    78.              break;
    79.              case "REQUEST":
    80.                 return $_REQUEST=array_merge((array)$_REQUEST,(array)$value);
    81.              break;
    82.              default;
    83.                 return $_POST=array_merge((array)$_POST,(array)$value);
    84.          }
    85.      }
    86.  
    87.  
    88. ###############################################
    89. # Parse Action Zone
    90. ###############################################
    91.  
    92.  
    93.      private function ParseNoEmpty($name,$row){
    94.          $value=$this->VarGet($name);
    95.          if(empty($value)){
    96.              return true;
    97.          }
    98.          return false;
    99.      }
    100.      private function ParseLimitLength($name,$row){
    101.          $value=$this->VarGet($name);
    102.          if(strlen($value)>$row['type_value']){
    103.              return true;
    104.          }
    105.          return false;
    106.      }
    107.      private function ParseMinLength($name,$row){
    108.          $value=$this->VarGet($name);
    109.          if(strlen($value)<$row['type_value']){
    110.              return true;
    111.          }
    112.          return false;
    113.      }
    114.      private function ParseInt($name,$row){
    115.          $value=$this->VarGet($name);
    116.          if(!is_numeric($value)){
    117.             return true;
    118.          }
    119.          return false;
    120.      }
    121.      private function ParseRegExp($name,$row){
    122.          $value=$this->VarGet($name);
    123.          if(!preg_match($row['type_value'],$value)){
    124.             return true;
    125.          }
    126.          return false;
    127.      }
    128.      private function ParseEscape($name,$row){
    129.          $value=$this->VarGet($name);
    130.          $this->VarSet(array($name=>Replacer::Escape($value)));
    131.          return false;
    132.      }
    133.      private function ParseAddSlashes($name,$row){
    134.          $value=$this->VarGet($name);
    135.          $this->VarSet(array($name=>support::SUaddslashes($value)));
    136.          return false;
    137.      }
    138.      private function ParseStripSlashes($name,$row){
    139.          $value=$this->VarGet($name);
    140.          $this->VarSet(array($name=>support::SUStripSlahes($value)));
    141.          return false;
    142.      }
    143.      private function ParseMReplace($name,$row){
    144.          $value=$this->VarGet($name);
    145.          $this->VarSet(array($name=>Replacer::Mreplace($value)));
    146.          return false;
    147.      }
    148.      private function ParseReplace($name,$row){
    149.          $value=$this->VarGet($name);
    150.          $this->VarSet(array($name=>Replacer::Replace($value)));
    151.          return false;
    152.      }
    153.      private function ParseR_Replace($name,$row){
    154.          $value=$this->VarGet($name);
    155.          $this->VarSet(array($name=>Replacer::R_Replace($value)));
    156.          return false;
    157.      }
    158.      private function ParseMd5($name,$row){
    159.          $value=$this->VarGet($name);
    160.          $this->VarSet(array($name=>md5($value)));
    161.          return false;
    162.      }
    163.      private function ParseNoHtml($name,$row){
    164.          $value=$this->VarGet($name);
    165.          $this->VarSet(array($name=>strip_tags($value)));
    166.          return false;
    167.      }
    168.      private function ParseHtmlDecode($name,$row){
    169.          $value=$this->VarGet($name);
    170.          $value=str_replace("<br>","\r\n",$value);
    171.          $this->VarSet(array($name=>htmlspecialchars(html_entity_decode($value,ENT_QUOTES))));
    172.          return false;
    173.      }
    174.      private function ParseNoInt($name,$row){
    175.          $value=$this->VarGet($name);
    176.          if(preg_match("#[0-9]+#is",$value))
    177.             return true;
    178.          return false;
    179.      }
    180.      private function ParseUserFunc($name,$row){
    181.          $value=$this->VarGet($name);
    182.          $funcs=explode(",",$row['type_value']);
    183.          $funcs=(array)$funcs;
    184.          for($i=0,$c=count($funcs);$i<$c;$i++){
    185.              $value=$funcs[$i]($value);
    186.          }
    187.          $this->VarSet(array($name=>$value));
    188.          return false;
    189.      }
    190.  
    191.  
    192. ###########################################
    193. # EOF
    194. ###########################################
    195.  
    196.  
    197.  
    198.      private function ErrorTpl($tplname,$vars=false){
    199.           $msg=self::$cnf['formvalidate_def_errors'][$tplname];
    200.           return $this->ErrorMsg($msg,$vars);
    201.      }
    202.      private function ErrorMsg($msg,$vars=false){
    203.          if($vars){
    204.            foreach((array)$vars as $key=>$val){
    205.                $msg=str_replace("{".$key."}",$val,$msg);
    206.            }
    207.          }
    208.          return $msg;
    209.      }
    210. }
    211. ?>
     
  12. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Экземпл использования еще б хорошо.
    и от твоего кода форум разъехался
     
  13. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Koc
    он требует ещё 2-4 класса =)
    а так, оч просто
    PHP:
    1. <?
    2. $fv=new FormValidate();
    3.        "name"=>array("noempty","regexp[#(?:[\w\.\-]+)\@(?:[\w\.\-]+)\.(?:\w+)#is]"),
    4.        "text"=>array(
    5.                array("noempty","Заполните поле текст"),
    6.                array("minlength[30]","Какого фига поле {name} короче 30 символов?"),
    7.                "replace","escape","userfunc[strtoupper,urlencode]"
    8.        ),
    9. ));
    10. if($err=$fv->CheckError()){
    11.   print_r($err);
    12. }else{
    13.   print "Всё ок";
    14. }
    15. ?>
     
  14. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
  15. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    а если через мой валидатор прогнать?
     
  16. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    http://cogear.ru/user_guide/gears/form_elements/
    валидация как в CI (оно и не мудрено, система на нем построена :) )
    Генерация форм в принципе тоже прикольная.

    А я, дурак, для каждой формы шаблон делаю. Пойду напьюсь с горя.
     
  17. kostyl

    kostyl Guest

    PHP:
    1. <?php
    2. Request::AddConstraint('reglogin', ST_POST, new Constraint(CT_MUSTMATCH, USER_LOGIN_MUTCH, Language::GetText('M_LOGIN_MUTCH_ERROR')));
    3. Request::AddConstraint('password', ST_POST, new Constraint(CT_MINLENGTH, MIN_USER_PSWD_LENGTH, Language::GetText('М_PASSWORD_MINLENGTH_ERROR')));
    4. Request::AddConstraint('password', ST_POST, new Constraint(CT_MAXLENGTH, MAX_USER_PSWD_LENGTH, Language::GetText('М_PASSWORD_MAXLENGTH_ERROR')));
    5. Request::AddConstraint('passwordagain', ST_POST, new Constraint(CT_EQUALTO, Request::GetPostVar('password'), Language::GetText('M_PASSWORD_AGAIN_ERROR')));
    6. Request::AddConstraint('email', ST_POST, new Constraint(CT_MUSTMATCH, USER_EMAIL_MATCH, Language::GetText('M_EMAIL_MUTCH_ERROR')));
    7. if (Request::TestConstraints() { ......
    8.  
     
  18. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    kostyl
    OMG! Kosteg, what is this?
     
  19. kostyl

    kostyl Guest

    Koc
    Проверка данных формы. Вариант реализации. А что?
     
  20. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    давно считается хорошим тоном проверять данные на стороне клиента, а потом конечно в скрипте.

    http://enigma.440hz.ru/

    я вот так извращаюсь.
    =)
     
  21. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    440Hz
    ExtJS в помощь =)
     
  22. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    че такое?
     
  23. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
  24. kostyl

    kostyl Guest

    440Hz
    Koc
    Не пойму чем моя реализация вам не нравиться?
     
  25. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Не то что б не нравится, в ней много букав, констант, оч много всего в верхнем регистре, для каждого правила свой объект (хотя не факт, что это минус). 440hz не говорил что не нравится, он просто сказал, дескать еще и на стороне клиента проверять нужно.

    зы: я закоммитил куски кода старые в свои "велосипедные библиотеки". Кому интересно - могу закоммитить туда же текущую версию