Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Автоматизация создания и валидации форм

Anna | 31.05.2014 | нет комментариев

Создание форм — один из самых ответственных процессов при создании всякого сайта. Эта часть сайта, как правило, в большей степени требует пристального внимание, Дабы недопустить разные неприятные обстановок. Для пользователей — это самый основной метод передачи информации на сервер, при котором необходимо контролировать передаваемые значения. Вероятно, 99% всех сайтов содержат формы, следственно верю, что статья сумеет облегчить жизнь, как минимум, начинающим web-программистам.
Топик не является начальством к действию и не призывает неизменно применять данную спецтехнологию создания форм и работы с ними. Статья рассчитана основным образом на программистов, которые до сих пор пишут формы и код валидации для всякого поля вручную.

Выходит, формы

 

<form name="loginform" action="/login" method="post" autocomplete="off">
...
<form>

Содержит ряд свойств и состоит из разных элементов, с поддержкой которых организуется ввод данных разного формата. Всякая форма имеет разные свойства, разное чисто элементов и их многообразие. Всякий раз, код должен контролировать корректность ввода ещё до отправки на сервер, Дабы пользователь не ожидал результата от сервера сообщения, которое пользователь может получить ещё до отправки данных на сервер. Это и Отчасти снижает нагрузку на сам сервер и сокращает время, которое пользователь тратит на ожидание результата. В свою очередь нужно дублировать проверку и на самом сервере, потому что пришедшим от заказчика данным невозможно доверять.

Вписывание в присутствующий движок сайта

Приведённые в статье примеры незначительно адаптированы под архитектуру MVC, но вы с лёгкостью можете подправить классы под свою архитектуру. Цель статьи — донести всеобщий правило, а не показать как необходимо писать код.
Неподвижная часть HTML-разметки находится в образцах. На 1-й взор навязывается вариант прописать формы в файлах образца. Но что если на вашем сайте предусмотрено огромное число форм? Да, дозволено потратить несколько дней, недельку, прописать все формы в образцах, дальше сделать JavaScript-код, тот, что бы валидировал формы на стороне заказчика перед отправкой, дальше сделать проверку всякого значения на стороне сервера и т.д. И всё это для всякой формы! Давайте посмотрим, как данный процесс дозволено оптимизировать и гораздо облегчить себе задачу. Оформим всё в виде классов и в последующем легко сумеем применять в последующих своих планах.

Сотворим в комфортном месте своего сайта директорию forms и в неё будем складывать файлы с изложением форм. Я использую для этого XML. Предлагаемый формат файла формы:

<?xml version="1.0" encoding="utf-8"?>
<validator method="post" action="/json/login">
<field type="word" name="username" req="true" value="" min="4" max="25">User name</field>
<field type="password" name="password" req="true" value="" min="4" max="25">User password</field>
<field type="submit">Log In</field>
</validator>

По изложению видно, что форма, состоящая из трёх элементов, должна отправиться способом POST на относительный адрес /json/login и имеет CSS-класс form.
Элементы формы:

  • Поле для ввода имени пользователя, с лимитацией по минимальной и максимальной длины вводимого текста
  • Поле для ввода пароля, с лимитацией по минимальной и максимальной длины вводимого текста
  • Кнопка для отправки формы

Основным признаком полей является TYPE, тот, что однозначно идентифицирует, какой HTML-элемент будет сделан на странице и какие значения в него дозволено будет вводить. Также будет механически сгенерирован код JavaScript для валидации непременных полей формы на стороне заказчика, а также на стороне сервера позже принятия значений формы.

Вставка формы в web-страницу

Для механической вставки формы на страницу, в образце в надобном месте вставим метку <!--[LOGIN]-->, д_onemk!<button onclick=”checkForm();return false;”>’.$this->value.’</button>’; } }

Вы спросите отчего кнопка именно такая? Я использую AJAX для отправки форм, следственно мне комфортен такой вариант, вы у себя можете сделать так, как вам комфортно.
Остальные элементы формы испробуйте написать сами по такому же тезису.

Базовая форма

По аналогии с элементами, формы тоже имеют комплект непременных для всех форм свойствами, следственно я решил сделать базовый класс для всех создаваемых форм:

class baseHTMLform
{
    protected $name, $action, $method, $class, $autocomplete;
    protected $elements = array();

    public function __construct($name, $action, $method, $class, $autocomplete=false)
    {
        $this->name     = $name;
        $this->action   = $action;
        $this->method   = $method;
        $this->class    = $class;
        If ($autocomplete == true)
        {
            $this->autocomplete = "on";
        }
        else
        {
            $this->autocomplete = "off";
        }
    }

    public function addElement($el)
    {
        $this->elements[] = $el;
    }

    public function show()
    {
        $html = '<div id="errortext"></div><form name="'.$this->name.'" action="'.$this->action.'" method="'.$this->method.'" autocomplete="'.$this->autocomplete.'"><table>';
        $js = '<script type="text/javascript" src="/js/api.js?rand=0.01"></script>';
        $js.= '<script type="text/javascript">function checkForm(){var el,elName,value,type,form;error=0;form=document.forms["'.$this->name.'"];for(var i = 0;i<form.length;i  ){el=form.elements[i];elName=el.nodeName.toLowerCase();value=$.trim(el.value);';
        foreach ($this->elements as $el)
        {
            $reqstar = '';
            If ($el->is_req())
            {
                $reqstar = '<em>*</em>';
            }
            $js .= $el->get_js();
            $html .= '<tr><td>'.$el->get_title().$reqstar.'</td><td>'.$el->get_html().'</td></tr>';
        }
        $html .= '</table></form>';
        $js .= '}if(error == 0){post("'.$this->name.'", "'.$this->action.'", "#errortext");}}</script>';
        return $js.$html;
    }
}

Класс реализует способы, создающие HTML-разметку формы и генерирующие валидационный JavaScript-код.
В листринге указан прикрепляемый файл api.js, это моя собственная библиотека, с поддержкой которой я по AJAX передаю форму на сервер и принимаю итог, а также реализовано изложение таких функций как showmessage.

Сборка формы из элементов и создание правил для вводимых значений

 

class formClass
{
    private $formfile, $name;

    public function __construct($name)
    {
        $this->formfile = '../application/forms/'.$name.'.xml';
        $this->name     = $name;
        if(!is_file($this->formfile)) new CustomException('Not found form: "'.$name.'"');
    }

    public function getHTML()
    {
        $xml   = simplexml_load_file($this->formfile);
        $form = new baseHTMLform($this->name, $xml['action'], $xml['method'], $xml['class']);
        $html = '';

        foreach ($xml->field as $element)
        {
            switch ($element['type'])
            {
                case "text":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $form->addElement($htmlElement);
                    break;
                case "password":
                    $htmlElement = new inputPasswordHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $form->addElement($htmlElement);
                    break;
                case "word":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('-_0-9a-zA-Zа-яА-Я');
                    $form->addElement($htmlElement);
                    break;
                case "submit":
                    $htmlElement = new submitHTMLelement($element);
                    $form->addElement($htmlElement);
                    break;
                case "alpha":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('a-zA-Zа-яА-Я');
                    $form->addElement($htmlElement);
                    break;
                case "alpha-number":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('0-9a-zA-Zа-яА-Я');
                    $form->addElement($htmlElement);
                    break;
                case "number-int":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('0-9');
                    $form->addElement($htmlElement);
                    break;
                case "time":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('-: 0-9 a-zA-Zа-яА-Я');
                    $form->addElement($htmlElement);
                    break;
                case "phone":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('-()  0-9');
                    $form->addElement($htmlElement);
                    break;
                case "strings-alpha":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_allow_char('/-a-zA-Zа-яА-Я, 0-9');
                    $form->addElement($htmlElement);
                    break;
                case "repassword":
                    $htmlElement = new inputPasswordHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->add_rule('if((el.name=="'.$element['name'].'")&(elName=="input")&(value!=form.password.value)){showmessage("['.$element.']: Password does not match");break;}');
                    $form->addElement($htmlElement);
                    break;
                case "email":
                    $htmlElement = new inputHTMLelement($element['name'], $element, $element['req']);
                    $htmlElement->setLenght($element['min'], $element['max']);
                    $htmlElement->setValue($element['value']);
                    $htmlElement->add_regex('^([a-z0-9 _-] )(.[a-z0-9 _-] )*@([a-z0-9-] .) [a-z]{2,6}$', 'Incorrect address format E-mail');
                    $form->addElement($htmlElement);
                    break;
                case "captcha":
                    $htmlElement = new captchaHTMLelement($element['name'], $element, $element['req']);
                    $form->addElement($htmlElement);
                    break;

            }
        }

        return $form->show();
    }

}

Как видно, не требуется создавать отдельные классы для всякого элемента с особенными правилами для вводимых значений, для этого довольно наделить правилами больше примитивный элемент.

Валидация на стороне сервера

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

$validForm = new validatorClass($this->params[1]);
$validForm->loadParams($this->post);
if ($validForm->isError == false)
     {
       // Ошибок нет, дозволено применять данные
     }
   else
     {
        // Значения не прошли валидацию, изложение ошибки хранится в $validForm->errorText
     }   

Дальше разглядим сам класс validatorClass:

class validatorClass
 {
   protected $src, $name;
   public $errorText, $isError;

    public function __construct($name)
   {
    $this->src = '../application/userdata/validator/'.$name.'Validator.xml';
    if(!is_file($this->src)) new CustomException('Not found: '.$this->src);
    $this->name = $name;
    $this->isError = false;
   }

   public function loadParams($params)
   {
    $xml = simplexml_load_file($this->src);
   foreach($xml->field as $field)
     {
       $value = $params[''.$field['name'].''];

       if (($field['req']=="true")and($field['type'] != "submit"))
        {
          if ($value == ""){$this->isError = true; $this->errorText = 'The < '.$field.' > field can not be empty';break;}
        }
       if (($field['min'])and($value))
        {
          $min = (int) $field['min'];
          if (mb_strlen($value, CHARSET) < $min){$this->isError = true; $this->errorText = 'Поле < '.$field.' > должно содержать минимум '.$min.' символов';break;}
        }
       if ($field['max'])
        {
          $max = (int) $field['max'];
          if (mb_strlen($value, CHARSET) > $max){$this->isError = true; $this->errorText = 'Поле < '.$field.' > превышает максимальных '.$max.' символа';break;}
        } 
       if ($field['type']=="word")
        {
         $pattern = '/^([-_0-9a-zA-Zа-яА-Я] )$/iu';
         $n = preg_match($pattern, $value);
         if ($n == 0){$this->isError = true; $this->errorText = 'The < '.$field.' > field can only contain';break;}
        }
       if ($field['type']=="email")
        {
         $pattern = '/^([a-z0-9 _-] )(.[a-z0-9 _-] )*@([a-z0-9-] .) [a-z]{2,6}$/';
         $n = preg_match($pattern, $value);
         if ($n == 0){$this->isError = true; $this->errorText = 'Incorrect E-mail format in '.$field.'field';break;}
        } 
     } 
   } 
 }

Класс не вовсе старательно оформлен, давным-давно им не занимался, но Дабы был внятен толк, я привёл его. Вы скорее каждого оформите его больше прекрасно.

Завершение

Предвижу, что многие начнут писать что-то как бы “Для чего изобретать велосипед?” и тому сходственное, следственно сразу отвечу:
— А вы учились писать на PHP, сразу применяя готовые библиотеки?

Учиться нужно — вникая во всё и экспериментируя с кодом. Я легко захотел написать свою реализацию, не потому что я считаю себя самым разумным, а потому, что я хочу писать, экспериментировать и напрягать мозги — я получаю от этого наслаждение. Верю, среди вас найдутся такие же.

А что касается профессиональных и высоко ответственных сайтов, однозначно нужно применять проверенные временем решения.

Спасибо за внимание!

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB