За чистый и ясный код!

Статьи на тему программирования под веб, используя PHP, MySQL, Jquery и многое другое

Валидация формы на фреймворке Kohana, класс Validation. Часть 2

Июль3
Если у тебя командировка в Краснодар, то лучшей гостиницы просто не найти!

Валидация формыВ первой части я рассказал как построить форму используя фреймворк Kohana, во второй части я хочу рассказать как происходит валидация формы и вывод ошибок.

Как обычно, для просмотра примера используем форму представленную тут.

Статья написано для работы с версией Kohana 3.3.0 (текущая версия на момент написания статьи)

Класс Validation (валидация формы)

Для чего вообще требуется валидировать данные? Есть много причин — защита от дурака, получения более правдивых данных, предотвращение XSS атак и тд. Лично для меня валидация занимает важное место в создании сайта, т.к. именно с правильными данными приходится потом работать и если не делать проверку, например, на номер телефона (цифры и некоторые символы), эл.почты, ссылки и тд, потом можно очень сильно поплатиться.

Например если не проверить вводимый регистрируемый эл.адрес хотя бы на правильность написания, то в дальнейшем юзеру не будет возможности восстановить пароль и будут куча писем в саппорт… или например, многие создатели сайтов просят ввести номер телефона для контакта, и юзеры вводят местные номера, но блин, этоже инет, откуда я знаю из какого города, страны этот юзер!!! А юзер не ввел код и все, поэтому лучше всего проводить валидацию и указывать юзеру, что он не прав и код города (оператора связи) вводить надо!

Рассмотрим основные методы для валидцаии класса.

Создание экземпляра класса Validation

Есть два способа, классический

$post = Security::xss_clean($this->request->post()); // данные массива $_POST обработанные от XSS
$valid = new Validation(array_merge($post, $_FILES)); //тут я передаю в валидатору сразу два массива данных $_POST и $_FILES

и с помощью паттерна фабрики

$post = Security::xss_clean($this->request->post()); // данные массива $_POST обработанные от XSS
$valid = Validation::factory(array_merge($post, $_FILES)); //тут я передаю в валидатору сразу два массива данных $_POST и $_FILES

Правила (rule, rules)

С помощью этих методов передается название поля, которое требуется провалидировать, и правило которое требуется для этого.

Например, необходимо, чтобы поле «Ваше имя» было заполнено, для этого создаем правило

$valid->rule('name', 'not_empty');

Первый параметр метода rule это название поля валидации в теге input формы, второй параметр это метод класса Valid который будет применен к этому полю. В ядре фреймворка в классе Valid.  Это самый простой метод валидации, т.к. он не требует дополнительных параметров, просто проверить данные на пустоту и все. Есть более сложные методы проверки, например когда вам нужно проверить данные и для этого требуется передать методу класса Valid дополнительные параметры, например проверить данные на соответствие регулярному выражению, тогда запись правила валидации выглядит немного иначе:

$this->template->form->type_error = array(
	'0'=>' ',
	'1'=>'изменение информации о сайте',
	'2'=>'стилистические, грамматические, орфогр. ошибки'
);
...
$valid->rule('type_error', 'regex', array(':value','/[1-2]+/'));

Разберем подробнее. Есть поле формы с именем type_error, это тег типа select в нём имеются 3 опции, так вот важно чтобы были выбраны опции со значениями 1 или 2, поэтому я решил сделать проверку выбора с помощью регулярного выражения. Поэтому вторым параметром я указываю название метода, который есть в классе Valid. Метод требует для работы 2 параметра

public static function regex($value, $expression)
{
	return (bool) preg_match($expression, (string) $value);
}

А данные для метода Valid::regex идут в 3-й параметром в методе проверки array(‘:value’,’/[1-2]+/’),
где :value — это текущее значение поля формы type_error,
‘/[1-2]+/’ — это регулярное выражение.

Теперь надеюсь понятно, как строятся правила валидации для полей формы. Это еще не все пояснения, дальше будет.

Бывает случаи, когда для одного поля требуется написать сразу несколько правил валидации. Можно воспользоваться методом $valid->rule(…) и написать их столько к полю, сколько нужно, а можно просто использовать другой метод $valid->rules(…) для добавления сразу нескольких правил валидации за один раз, рассмотрим пример.

В форме есть поле email, это поле обязательно для заполнения, следовательно оно не должно быть пустым, еще нужно проверять,чтобы длина эл. адреса не превышала 254 символов, а еще чтобы туда был введен правильные электронный адрес, следовательно мне нужно использовать 3 правила валидации.

$valid->rules(
	'email', array(
		array('not_empty'),
		array('max_length', array(':value', 254)),
		array('email')
	)
);

Способом выше можно записать сразу все правила валидации для одного поле, обратите внимание, что метод Valid::max_length требует 2 параметра, значение и максимальную длину, которую я и передал.

Это способы которые идут «из коробки», но бывают ситуации, когда нужно проверить данные таким способом, который не описан в классе Valid, например проверить Captcha, на пустоту поля проверить можно, а вот правильность ввода как? Также есть решения:

$valid->rules(
	'captcha', array(
		array('not_empty'),
		array('Captcha::valid')
	)
);

Передаем сразу все правила за один раз в валидатор, проверяем на пустоту, стандартным методов Valid::not_empty, а также на корректность ввода, но обработку данных будет уже вести метод Captcha::valid, класс расположен в модуле Captcha. Еще пример такой же записи, теперь для картинок.

$valid->rule('img', 'Upload::type', array(':value', array('jpg', 'png', 'gif')))

Требуется загружать файлы, только с расширениями ‘jpg’, ‘png’, ‘gif’, за эту валидация отвечает метод Upload::type, который требует 2 параметра, данные и типы файла.

Как создать свой собственный валидатор я расскажу в следующей статье, а теперь переходим к другим метода класса валидации — label и labels.

Метки (label, labels)

Метод label нужен для вывода ошибок, а также получения переводов ошибок, об этом чуть позже. Пока расскажу как с ним работать.

Переменная $_labels внутри класса Validation заполняется самостоятельно при создании правил валидации, в дальнейшем по данным массива этих меток находятся переводы для заполнения массива ошибок, об этом тоже чуток позже. Но есть нюансы, в самом месте где происходит заполнение стоит регулярное выражение, которые удаляет «лишние» символы из название полей:

$this->_labels[$field] = preg_replace('/[^\pL]+/u', ' ', $field);

поэтому если у вас имеется в названии поля -, _ и прочие знаки, вам нужно указать это в методе $valid->label(…). В моём примере также имеется поле с «неправильным названием» type_error и для того, чтобы метка не изменилась, я указываю её:

$valid->label('type_error', 'type_error');

Конечно можно и поступить иначе, ошибки формы и переводы также буду показываться, даже если не указывать метку для «проблемного» поля, но я предпочитаю единообразие в назывании, чтобы через какое-то время не вспоминать, а чего тут поле называется type_error, а в переводах оно «type error«. Метод $valid->labels(…) принимает просто массив меток с параметром ключ=>значение, просто за один метод передать все данные формы.

Вывод ошибок (errors)

При валидации формы необходимо, в случае ошибок валидации, уведомлять об этом пользователя, что в таком-то поле вы что-то не то сделали. Для таких целей существует метод $valid->errors(…), рассмотрим его работу:

public function errors($file = NULL, $translate = TRUE){...}

Методу для работы требуется 2 параметра — название файла, в котором содержатся объяснения ошибок или переводы этих ошибок, второй параметр отвечает за перевод, по-умолчанию перевод включен.
Я назвал свой файл contact, сам файл можно размещать либо в модуле, либо в главной папке (application/messages/), запомните, что если будет находится 2 одинаковых файла в главной папке и в модуле (пример /modules/modulename/messages/), то данные будут прочитаны из главной папки, т.к. у Kohana такая иерархия обхода директорий. Т.к. модуля у меня нет, то я все примеры и переводы храню в главной папке (/application/messages/contact.php), вот его содержание:

<?php defined('SYSPATH') or die('No direct script access.'); 
$messages = array(
 	'name'	=>
		array(
			'not_empty'    	=> ':field must not be empty',
		),
	'email'	=>
		array(
			'not_empty'    	=> ':field must not be empty',
			'max_lenght'  	=> ':field must not exceed :param2 characters long',
			'email'			=> ':field not email address'
		),
	'sex'	=>
		array(
			'not_empty'    	=> ':field must not be empty',
		),
	'type_error'	=>
		array(
			'regex'    	=> ':field does not match the required format',
		),
	'descr'	=>
		array(
			'not_empty'    	=> ':field must not be empty',
		),
	'img'	=>
		array(
			'Upload::not_empty' => ':field must not be empty',
			'Upload::type' => ':filed is not allowed file type',
		),

	'captcha'	=>
		array(
			'Captcha::valid'=> ':field captcha not valid'
		),
);

return $messages;

На примере кусочка файла разберем его структуру, для примера возьмем эту часть:

'email'	=>
	array(
		'not_empty'    	=> ':field must not be empty',
		'max_lenght'  	=> ':field must not exceed :param2 characters long',
		'email'		=> ':field not email address'
	),

где, email — название поля в форме,
далее массив, в котором имеются ключи — это название метода в классе проверки, в данном случае Valid::not_empty и тд.
Ключ not_empty имеет значение :field must not be empty, что это? В ядре фреймворка имеется изначальный файл переводов (только английский язык), при проверке именно английское название будет выводится, часть начинающаяся с двоеточий :field будет заменена на название проверяемого поля, вот что получится — email must not be empty, вроде бы ура, всё ясно, но это не по-людски, нужна так выводить ошибки, чтобы человек мог понять, что от него просят! Поэтому нужно оформить переводы, т.к. у меня только русская локаль, то перевод я сделаю для неё, по аналогичной схеме можно делать переводы и для других языков. Конечно можно сделать халтуру и просто написать свой перевод вместо значения :field must not be empty, что-то типа, «Заполните электронный адрес!«, но в таком случае на всех языках сайта будут только один перевод на одном языке.

Немного о том, как создавать файл переводов. Файлы переводов хранятся или в главной папке application/i18n или в файле модуля, подчиняется тем же правилам считывания, что и все файлы фреймворка. В папке переводов i18n создается папка с двухзначным буквенным кодом локали в нижнем регистре, по ISO 639-1 (смотрите Вики), далее в этой папке будет файл с переводами, файл также создается по ISO 639-1 в нижнем регистре, например для русского языка будет ru, т.е. получится такая цепочка application/i18n/ru/ru.php или, для Украины, application/i18n/uk/ua.php, для Британии application/i18n/en/gb.php и тд.

Пример файла перевода:

<?php defined('SYSPATH') or die('No direct script access.'); 
return array(
  	// Переводы для валидации
  	':field must not be empty'  => 'Поле "<span>:field</span>" не должно быть пустым.',
	':field not email address'  => 'Поле "<span>:field</span>" содержит не корректный e-mail адрес.',
	':field captcha not valid'	=> 'В поле "<span>:field</span>" введён не верный код.',
	':filed is not allowed file type' => 'Файл в поле "<span>:field</span>" должен иметь расширения <span>:param2</span>.',
	':field does not match the required format'         => 'Поле "<span>:field</span>" не выбрано',
	':field must not exceed :param2 characters long' => 'Поле "<span>:field</span>" имеет длину больше чем <span>:param2</span> символа.',

	// Переводы для полей форм
	'name' => 'Ваше имя',
	'email' => 'Ваш эл. адрес',
	'sex' => 'Укажите Ваш пол',
	'type_error' => 'Тип проблемы',
	'descr' => 'Описание проблемы',
	'captcha' => 'Введите код',
	'img' => 'Картинка с ошибкой'
);

где, ключ — можно найти в файле contact.php, все такие названия будут заменены на значения файла перевода,
ну а значение ключа — это и есть перевод.

В переводах можно заметить некие сущности, такие как :field, :param2 и тд, эти сущности будут подменяться на название поля для :field и значение которое мы передаем в правиле для валидации.
Например, если посмотреть на одно из правил валидации поля эл. адреса, то можно увидеть, что мы передаем в метод валидации некие параметры array(‘max_length’, array(‘:value’, 254)), вот эти параметры можно получить в выводе ошибок, например второй параметр имеет сущность :param2 и будет равен 254, и полный текст ошибки будет такой «Поле «Ваш эл. адрес» имеет длину больше чем 254 символа.»

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

Многие могут спросить, а зачем заполнять массив в файле contact.php? Да, можно просто оставить пустой массив, а использовать только файлы-переводов, но файл contact.php должен быть, иначе получите не информативный массив ошибок, с котором ничего не сделаешь. Если массив файла contact.php будет пуст, то весь перевод будет браться из файлов-переводов и эти ошибки будет ОДИНАКОВЫ для всех форм на сайте, если же вы хотите вывести другое описание ошибки с одинаковым типом ошибки, то вам нужно заполнить массив и значение перевода выдумать своё, а далее это значение написать в файл переводов и для одной из форм у вас будет иной перевод.

Пример:

файл application/messages/contact.php
<?php defined('SYSPATH') or die('No direct script access.');
$messages = array(
 	'sex'	=>
		array(
			'not_empty'    	=> 'pol_ukagi',
		),
);

return $messages;

файл application/i18n/ru/ru.php
<?php defined('SYSPATH') or die('No direct script access.');  
return array(
 	// Переводы для валидации
  	'pol_ukagi'  => 'А вы кто, девочка или мальчик?',
);

После это вывод поля sex измениться с Поле «Укажите Ваш пол» не должно быть пустым. на А вы кто, девочка или мальчик?.

Теперь у вас все сделано для оформления ошибок, хочу еще сказать как получить массив всех этих ошибок. Как раз метод $valid->errors(‘contact’); и выдаст массив ошибок, где ключ — название поля, а значение отформатированное название ошибки. Далее делайте с ним, что вы хотите, например я во вьюхе пробежался по нему циклом и вывел все ошибки.

Контроллер

Хочу показать оформление контроллера.

public function action_index()
{
	$this->template->title = 'Пример работы валидатора';
	$this->template->form = new View('form_contact');
	$this->template->form->type_error = array(
		'0'=>' ',
		'1'=>'изменение информации о сайте',
		'2'=>'стилистические, грамматические, орфогр. ошибки'
	);

	$post = $this->request->post();

	if (count($post) > 0)
	{
		$post = Security::xss_clean($post);

		$valid = new Validation(array_merge($post, $_FILES));

		$valid->rule('name', 'not_empty', array(':value'))
			 ->rules(
				 'email', array(
					 array('not_empty'),
					 array('max_length', array(':value', 254)),
					 array('email'),
				 )
			 )
			 ->rule('sex', 'not_empty')
			 ->rule('type_error', 'regex', array(':value','/[1-2]+/'))->label('type_error', 'type_error')
			 ->rule('descr', 'not_empty')
			 ->rule('img', 'Upload::type', array(':value', array('jpg', 'png', 'gif')))
			 ->rules(
				'captcha', array(
						array('not_empty'),
						array('Captcha::valid')
					)
				)
		;

		if ($valid->check())
		{
			print_r($valid->data()); // валидированные данные
			print_r($post); // пост данные
			print_r($_FILES); // данные файлов
			exit;
		}
		else
		{
			$this->template->form->errors = $valid->errors('contact');
		}
	}
}

Как видно из контроллера, мы получаем переменную post() c данными формы, прогоняем данные через очистку от XSS, далее создаем экземпляр класса валидации, куда передаем смешанный массив данных для валидации, далее оформляем правила валидации, и осуществляем проверку, прошли проверку валидации — вывели данные массивов, а там делайте с ними, что вам угодно, не прошли валидацию — получите список ошибок валидации.

Валидация через ORM

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

Статья просмотренна 660534 раз, зашло посетителей 68038

Создание и валидация формы на фреймворке Kohana. Часть 1

Январь13

ФормыКакие теги используются при создании формы я описывал в предыдущей статье. В этой статье я хочу описать как построить форму используя фреймворк Kohana. Я буду использовать только родные средства для построения и валидации формы. Есть много сторонних средств для работы с формой, но их описание выходит за рамки данной статьи.

На правах рекламы — интересный СЕО блог.

Для пример возьмем форму по этой ссылке.

Описание класса Form в Kohana

Для построения формы используется класс Form. Методы класса все статические, доступ к методам осуществляется через ::, например Form::input(…); Если так написать, то будет создан тег input и т.д.

Основная часть методов, которые формируют теги первым параметром принимает значение атрибута name,т.е. название переменной которое будет со своим значением передано на сервер. Вторым параметром принимается значение для создаваемого тега, для тега input это значение атрибута value, для тега select это массив, ключи которого есть значение тега option, а значение массива это то, что стоит между тегом option. Третьим параметров, в основном, принимается массив дополнительных атрибутов для создаваемого тега. Ключ массива это название атрибута, а значение массива — это значение атрибута, например array(‘id’=>’id_tag’).

Опишем более подробно.

Создание тега form

Для этого используется метод Form::open. В качестве первого аргумента он принимает значение атрибута action, но можно передавать NULL, тогда значение урла будут соответствовать текущей странице. Если передать пустоезнавение ‘ ‘, то тогда урл будет браться из переменной Kohana::base_url, которую мы задаем в bootstrap.php.

Вторым значение элемента передается массив других атрибутов для данного тега.

<!--?php echo Form::open(NULL, array('id'=-->'contact', 'enctype'=>'multipart/form-data'));?>

будет выведено</pre>
<form id="contact" action="/contact" method="post" enctype="multipart/form-data" accept-charset="utf-8">

Для закрытия тега формы применяется метод Form::close, он не принимает никаких параметров.

<!--?php echo Form::close();?-->

будет выведено

Создание тега input

Для создание этого тега предназначен метод Form::input.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это значение атрибута value=’value’
Третий параметр это массив с данными по атрибутам.

<!--?php echo Form::input('name', Security::xss_clean(Arr::get($_POST, 'name', '')), array('id'=-->'name'));?>

будет выведено

<input id="name" type="text" name="name" value="" />

В атрибутах можно передать тип для тега input и видоизменить форму, можно сделать тип пароль, чекбокс, рейдиобатон и тд, но есть и отдельные методы которые просто реализуют некоторые типы, наверное это сделано для удобства понимая кода. К таким метода относятся Form::hidden, Form::password, Form::file.

Для создания чекбосков используется метод Form::checkbox. Все параметры похожи, имя, значение, выбран или нет элемент и массив атрибутов. Особо можно выделить третий параметр $checked он принимает истину или ложь и показывает выбран данный элемент формы или нет.

<!--?php echo Form::radio('sex', 1, ((isset($_POST['sex']) AND $_POST['sex']==1) ? TRUE : FALSE), array('id'=-->'your_sex_mail'));?>
<!--?php echo Form::checkbox('track', 0, (isset($_POST['track']) ? TRUE : FALSE), array('id'=-->'track'));?>

будет выведено, соответственно

<input id="your_sex_mail" type="radio" name="sex" value="1" />
<input id="track" type="checkbox" name="track" value="0" />

Создание тега textarea

Для создание этого тега предназначен метод Form::textarea.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это сам текст который оказывается внутри тега.
Третий параметр это массив с данными по атрибутам.
Четвертый параметр предназначен для двойной кодировки спецсимволов, смотрите ф-цию htmlspecialchars

<!--?php echo Form::textarea('descr', Security::xss_clean(Arr::get($_POST, 'descr', '')), array('id'=-->'descr'));?>

будет выведено, соответственно

<textarea id="descr" name="descr" rows="10" cols="50"></textarea>

Создание тега select

Для создание этого тега предназначен метод Form::select.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это массив с данными.
Третий параметр это или массив значений или значение выбранного элемента
Четвертый параметр это массив с данными по атрибутам.

Также этот тег позволяет построить вспомогательный элемент optgroup. Для его создания необходимо передавать массив, у которого в качестве ключа будет название группы а значение это будет вложенный массив ключ=>значение для элемента option.

<!--?php echo Form::select('type_error', array('0'=-->' ', '1'=>'изменение информации о сайте', '2'=>'стилистические, грамматические, орфогр. ошибки'), (isset($_POST['type_error']) ? $_POST['type_error'] : 0), array('id'=>'type_error'));?>

будет выведено, соответственно
<select name="type_error"> <option selected="selected" value="0"> </option></select>
<select name="type_error"> <option value="1">изменение информации о сайте</option></select>
<select name="type_error"> <option value="2">стилистические, грамматические, орфогр. ошибки</option></select>

Создание тега label

Первый параметр принимает значение ИД основного элемента формы, к которому привязан.
Второй элемент показывает описание к тегу.
Третий параметр — массив атрибутов.

<!--?php echo Form::label('email', __('Ваш эл. адрес').':'.'<span--> *');?>
<!--?php echo Form::input('email', Security::xss_clean(Arr::get($_POST, 'email', ' ')), array('id'=-->'email'));?>

будет выведено, соответственно

<label for="email">Ваш эл. адрес:<span> *</span></label>
<input id="email" type="text" name="email" value="" />

Остальные теги

В данном классе есть еще методы — submit, image, button. Все они являются частным случаем тегом input.

Пример построения формы

Тут привожу код вьюхи, формы которую рассматриваем.

</pre>
<h1></h1>
<pre>
<!--?php echo Form::open(Request::instance()--->uri, array('id'=>'contact', 'enctype'=>'multipart/form-data'));?>

<!--?php if(isset($errors) AND count($errors)-->0):?>
	<!--?php echo View::factory('errors')--->bind('errors', $errors)?>
<!--?php endif;?--></pre>
<div class="require"></div>
<fieldset title="<?php echo __('Ваши данные');?><br />">
<legend><!--?php echo __('Ваши данные');?--></legend>
<ul>
	<li><!--?php echo Form::label('name', __('Ваше имя').':'.'<span--> *');?>
 <!--?php echo Form::input('name', Security::xss_clean(Arr::get($_POST, 'name', '')), array('id'=-->'name'));?></li>
	<li><!--?php echo Form::label('email', __('Ваш эл. адрес').':'.'<span--> *');?>
 <!--?php echo Form::input('email', Security::xss_clean(Arr::get($_POST, 'email', '')), array('id'=-->'email'));?></li>
	<li class="sex">
<div></div>
 <!--?php echo Form::label('your_sex_mail', __('муж').':');?-->
 <!--?php echo Form::radio('sex', 1, ((isset($_POST['sex']) AND $_POST['sex']==1) ? TRUE : FALSE), array('id'=-->'your_sex_mail'));?>
 <!--?php echo Form::label('your_sex_femail', __('жен').':');?-->
 <!--?php echo Form::radio('sex', 0, ((isset($_POST['sex']) AND $_POST['sex']==0) ? TRUE : FALSE), array('id'=-->'your_sex_femail'));?></li>
</ul>
</fieldset>
<fieldset title="<?php echo __('Ваш вопрос');?><br />">
<legend><!--?php echo __('Ваши вопрос');?--></legend>
<ul>
	<li><!--?php echo Form::label('type_error', __('Описание проблемы').':'.'<span--> *');?>
 <!--?php echo Form::select('type_error', $type_error, (isset($_POST['type_error']) ? $_POST['type_error'] : 0), array('id'=-->'type_error'));?></li>
	<li><!--?php echo Form::label('descr', __('Описание проблемы').':'.'<span--> *');?>
 <!--?php echo Form::textarea('descr', Security::xss_clean(Arr::get($_POST, 'descr', '')), array('id'=-->'descr'));?></li>
	<li><!--?php echo Form::label('img', __('Картинка с ошибкой').':');?-->
 <!--?php echo Form::file('img', array('id'=-->'img'));?></li>
	<li><!--?php echo Form::label('track', __('Отслеживать вопрос').':');?-->
 <!--?php echo Form::checkbox('track', 0, (isset($_POST['track']) ? TRUE : FALSE), array('id'=-->'track'));?></li>
</ul>
</fieldset>
<ul class="captcha">
	<li></li>
	<li><!--?php echo Form::label('captcha', __('Введите код').':'.'<span--> *');?>
 <!--?php echo Form::input('captcha', NULL, array('id'=-->'captcha'));?></li>
</ul>
<div class="buttons"></div>
<pre>
<!--?php echo Form::close();?-->

Небольшое описание.
$errors — это переменная которая в себе будет нести ошибки при валидации формы;
Security::xss_clean(Arr::get($_POST, ‘descr’, »)) — это часть чистит вводимые значение от XSS, а также подставляет дефолтное значение если нет значение текущей переменной, а данном случае descr.

Описание контроллера, валидации приведу в следующей статье.

Статья просмотренна 148511 раз, зашло посетителей 33963

Веб формы. Основые построения на XHTML

Декабрь23
Светодиодные лампы лб производства Feron.

Вступление

По своей работе я создаю очень много разных и разнообразных веб форм. С использованием ajax, jQuery и тд. Веб формы от маленькой до великой. У меня накопился довольно большой багаж знаний с которыми я и хочу поделиться. Я хочу написать цикл статей посвященных построению веб форм, далее просто формы, их обработке с помощью фреймвеорка Zendframework и Kohana. Начну я с самого начало — построение формы на чистом XHTML.

Хочу сразу предупредить людей которые знают как строиться форма, какие бывают атрибуты, элементы и их особенности — статья не для вас, поэтому писать в комментариях «для зеленных» не стоит. Можете перейти к другим статьям.

Что есть форма

Определение формы пипец как много…. В данном контексте под формой подразумевается набор тегов которые позволяют передавать вводимую информацию от клиента на сервер.

Все мы часто заполняем разные формы. Начиная с нашего рождения (бланк о рождении) и заканчивая смертью (справка о смерти). В течении дня люди разных профессия заполняют разные формы, мы программисты наверное каждый день заполняем какие-то формы комментариев, электронных писем и т.д. Форма на сайте — очень важная часть страницы, которая позволяет нам общаться.

При построении формы надо уделить много времени деталям. Форма должна быть интуитивно понятна, должна быть сделана для разных категорий людей, не стоит забывать об инвалидах. Очень много внимание форме уделяется дизайнером, юзабилити — специалистом, специалистом по безбарьерности и т.д…

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

Пример построения формы

Начнем с небольшого примера, в который я попытался собрать все теги, которыми обладает XHTML для построения формы.

Пример формы

Пример формы

Ссылка на пример формы

Во всех последующих примерах я буду брать за основу эту форму.

Ниже приведены коды для построения этой формы.

<h1>Контактная форма</h1>
<form action="/contact" method="post" id="contact" accept-charset="utf-8" enctype="multipart/form-data">
	<div class="require">Поля помеченные знаком <span>*</span> обязательны для заполнения</div>
	<fieldset title="Ваши данные"><br />
		<legend>Ваши данные</legend>
		<ul>
			<li>
				<label for="name">Ваше имя:<span>&nbsp;*</span></label><br />
				<input type="text" id="name" name="name" value="" />
			</li>
			<li>
				<label for="email">Ваш эл. адрес:<span>&nbsp;*</span></label><br />
				<input type="text" id="email" name="email" value="" />
			</li>
			<li class="sex">
				<div>Укажите Ваш пол:<span>&nbsp;*</span></div>
				<label for="your_sex_mail">муж:</label><br />
				<input type="radio" id="your_sex_mail" name="sex" value="1" /><br />
				<label for="your_sex_femail">жен:</label><br />
				<input type="radio" id="your_sex_femail" name="sex" value="0" />
			</li>
		</ul>
	</fieldset>
	<fieldset title="Ваш вопрос">
		<legend>Ваши вопрос</legend>
		<ul>
			<li>
				<label for="type_error">Описание проблемы:<span>&nbsp;*</span></label></p>
				<select id="type_error" name="type_error">
					<option value="0" selected="selected"></option><br />
					<option value="1">изменение информации о сайте</option><br />
					<option value="2">стилистические, грамматические, орфогр. ошибки</option><br />
				</select>
			</li>
			<li>
				<label for="descr">Описание проблемы:<span>&nbsp;*</span></label><br />
				<textarea id="descr" name="descr" cols="50" rows="10"></textarea>
			</li>
			<li>
				<label for="img">Картинка с ошибкой:</label><br />
				<input type="file" id="img" name="img" />
			</li>
			<li>
				<label for="track">Отслеживать вопрос:</label><br />
				<input type="checkbox" id="track" name="track" value="0" />
			</li>
		</ul>
	</fieldset>
	<ul class="captcha">
		<li>
			<span class="code">Код:</span><br />
			<span id="img"><img src="/captcha/default" alt="Введите код указаный на картинке" class="capt" /></span><br />
			<span id="change_captcha">сменить код</span>
		</li>
		<li>
			<label for="captcha">Введите код:<span>&nbsp;*</span></label><br />
			<input type="text" id="captcha" name="captcha" />
		</li>
	</ul>
	<div class="buttons">
		<input type="submit" name="submit" value=" ОТПРАВИТЬ" />
	</div>
</form>

Описание тегов и их атрибутов

Теги которые используются для построения формы:

<form>

С этого тега начинается форма. Форма в форме не существует!!! Кол-во форм на странице может быть много.

Каждый тег имеет свои атрибуты, которыми задается свойство тега.

Данный тег имеет следующие атрибуты:

action — в этот атрибут указывает путь к скрипту который будет обрабатывать данные формы. Атрибут может быть пустой, тогда за путь принимается текущий адрес страницы. Также можно указать путь на другой сервер, например вы можете построить на своём сайте поисковую форму какого-нибудь поисковика и в этом атрибуте указать адрес этого поисковика. После отправки данных формы, браузер перебросит вас на указанный урл, и если все параметры формы заданы правильно, то поисковик покажет ответы на заданный вопрос.

<form action="/contacts">....</form>

method — Есть два значения GET и POST (не чувствительны к регистру). Это способ передачи данных серверу.

Метод GET он стоит по-умолчанию, говорит серверу о том, что данные формы будет переданы, как параметры к урлу указанному в атрибуте action. С помощью метода GET передать файлы невозможно!!! Обычно такой метод формы используется для поисковых запросов.

<form action="/contacts" method="get">
	<input type="text" name="data" value="some value" />
	<input type="submit"  name="send" value="send data" />
</form>
в урле будет
http://test/contacts?data=some+value&send=send+data

Метод POST в отличии от метода GET ничего не добавляет к обрабатываемому УРЛу, а передает все данные формы через заголовки (юзеру явно не видно какие параметры передаются). Данный метод позволяет передать файлы.

<form action="/contacts" method="post">
	<input type="text" name="data" value="some value" />
	<input type="submit"  name="send" value="send data" />
</form>
в заголовках посланных к серверу будет следующее
POST /contacts HTTP/1.1
Host: test
....
я вырезал параметры не относящиеся к примеру
....
Content-Length: 30
data=some+value&send=send+data

enctype — этот атрибут указывает какой тип контента будет передаваться формой (просто текст или текст + файлы), если ничего не указано, то берется значение по-умолчанию application/x-www-form-urlencoded — означает что некоторые символы при передаче данных будут кодировться в предыдущих примерах, видно что вместо пробела появляется знак + data=some+value.

Если надо передать файлы + текст надо использовать тип multipart/form-data.

<form action="/contacts" method="post" enctype="multipart/form-data">
	<input type="file" name="somefile" />
	<input type="submit"  name="send" value="send data" />
</form>

accept — этот атрибут я не видел в использовании, он есть в документации, но чтобы он так сильно работал я не видел. Он позволяет определить какой тип файла должен обрабатывать сервер, но как показывает практика серверу по барабану!

<form action="/contacts.php" method="post" enctype="multipart/form-data" accept="image/png, image/gif">
	<input type="file" name="somefile" />
	<input type="submit"  name="send" value="send data" />
</form>
по-идеи должен только обрабатывать картинки типа png, gif.
Но на деле пропускает все подряд ... может есть какие-то
тонкие настройки сервера...

name — просто название формы. Должно начинаться с буквы ([A-Za-z]), за которой может следовать любое число букв, цифр ([0-9]), символов переноса (‘-‘), символов подчеркивания (‘_’), двоеточий (‘:’) и точек (‘.’).

accept-charset — указывает серверу в какой кодировке принимать данные формы.

<form action="/contacts.php" method="post" enctype="multipart/form-data" accept-charset="WINDOWS-1251">
	<input type="text" name="somefile" value="привет"/>
	<input type="submit"  name="send" value="send data" />
</form>
Сама страница документа у меня UTF-8, но в форме я указал WINDOWS-1251.
В результате данные формы на сервер пришли в кодировке 1251.
<form action="/contacts.php" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
	<input type="text" name="somefile" value="привет"/>
	<input type="submit"  name="send" value="send data" />
</form>
теперь UTF-8.

Если в параметр опускать, то кодировка соот. кодировке страницы.

onsubmit и тд — это методы для JavaScript их довольно много. Описывать в рамках этой статьи я не пока не буду.

class — указывает название класса для оформления формы стилями

style — указывает сами стили для оформления

<input>

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

Имеет следующие атрибуты (основные):

id — уникальный идентификатор тега в рамках загруженной страницы

type — самый важный параметр, который определяет внешний вид формы.

Если тип не указан, то принимается тип по-умолчанию type=’text’. Это означает что данное поле может принимать и отправлять на сервер любые строчные данные, т.е. те которые можно набрать на клавиатуре.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’password’ этот тип предназначен для поле в которое вводиться пароль или какая-то информация, которая, по-вашему мнению, обладает секретностью. Это не значит, что ваши данные как-то шифруются, просто при их вводе вместо вводимых символов показываются какие-то однотипные знаки. В каждой операционке они могут быть разными. При использовании тега с этим атрибутом не следует указывать секретную фразу в значении атрибута value, иначе при просмотре кода страницы можно легко узнать этот секрет, значение этого атрибута должно быть всегда пустым.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’radio’ этот тип предназначен для выбора из множества значений одного значения. Например, в рассматриваемой форме нам надо выбрать пол, т.е. из двух значений — мужской и женский пол (множество) какого-то одного. Но здесь есть один прикол. При формировании тега с данным типом, необходимо указывать одинаковое значение в атрибуте name.

<input type="radio" name="sex" value="мужской"/>
<input type="radio" name="sex" value="женский"/>

Также если при начальной загрузке страницы необходимо показать какой-то из элементов выбранным, то используется атрибут checked=’checked’.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’checkbox’ этот тип предназначен для выбора из множества значений, одного, нескольких или всех. Для этого типа, в отличии от типа type=’radio’ значение атрибута name должны быть разными.

<input type="checkbox" name="checkbox1" value="привет1"/>
<input type="checkbox" name="checkbox2" value="привет2"/>

Также если при начальной загрузке страницы необходимо показать какой(ие)-то из элементов выбранным(и), то используется атрибут checked=’checked’.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’file’ этот тип предназначен для загрузки файлов на сервер. Обратите внимание, что для загрузки файлов на сервер нужно иметь определенное значение атрибута ….. тега form (детальней читайте в описании тега form). Размер и тип загружаемого файла зависит от настроек сервера.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’submit’ этот тип предназначен для отправки всех данных формы на сервер.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’reset’ этот тип предназначен для очистки всех полей формы. Т.е. вы что-то набираете и захотели все стереть, нажимая на кнопку с соот типом все введенная инфа удаляется, форма переходит в состояние в котором она была загружена на страницу. Заметьте, если в форме уже стоят какие-то значения, то они удалены не будут!!!

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’image’ этот тип предназначен для отправки данных на форму, аналогичен тегу с типом submit, но разница только в том, что вместо кнопки можно подставлять любое изображение, также, если форма с методом GET, то в УРЛе появляются дополнительные переменные — координаты клика по рисунку, пример

http://example.com/?key=value&img.x=7&img.y=10

где img - это аттрибут name тега с типом image

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

name — имя тега, оно же имя переменной, которая принимает значение атрибута

value значение переменной с именем в атрибуте name, которое передается на сервер.

maxlenght — указывает на максимальную длину данных в элементе, если тип элемента text

checked в элементах формы с типом radio и checkbox указывает на выбранный элемент или элементы если тип checkbox.

disabled — Предназначен для отключения передачи данных элемента формы серверу. Переменная просто не передается вообще.

readonly — означает, что данные этого тега будут доступны только для чтения, изменять их нельзя. В отличии от атрибута disabled данные тега отправляются на сервер.

class — класс для стилей

style — предназначен для описания стилей данного элемента

onClick и д.р. события предназначенный для JavaScript. Описание выходит за рамки данной статьи

<select>

Тег предназначен для выбора или одного значения или множества из списка. Для выбора множества значения должен стоять атрибут multiple=’multiple’, атрибут name должен содержать название переменной и иметь в конце квадратные скобки [] — указывает, что возможна передача не одного значения, также атрибут size=’число’ указывает кол-во видимых элементов. Выбор множества осуществляется с удержанием клавиши ctrl и кликом на выбираемый элемент списка.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

<option>

Являеться частью тега select и предназначен для вывода одного элемента списка. Содежит атрибут value в который записывается значение, которое передается на сервер. Между открывающимся и закрывающимся тегом option содержится название описываемой переменной. Обычно в атрибуте value содержаться ID элементов, а между тегами значение элементов

<option value="1">apple</option>
<option value="2">pear</option>
<option value="3">cherry</option>

<optgroup>

Тег предназначен для разделения на группы элементов списка, например надо выделить группу фрукты и овощи в одном списке. Внутри тега содержаться список параметров, теги option. Сам тег optgroup имеет атрибут label — это текст которым называют выделенную группу.

Пример:

<optgroup label="фрукты">
	<option value="1">Апельсинка</option>
	<option value="2">Мандаринка</option>
	<option value="3">Лимончик</option>
</optgroup>
<optgroup label="овощи">
	<option value="4">Кабачок</option>
	<option value="5">Помидорка</option>
	<option value="6">Огурчик</option>
</optgroup>

Внешний вид тега:
Внешний вид тега optgroup

<textarea>

Тег предназначен для ввода и отправки текста с переносами строк. Отличается от тега <input type=’text’>, тем что поддерживается перенос строк.
Внешний вид элемента (размер) можно указывать с помощью стилей или с помощью атрибутов rows высота поля в строках текста, атрибут cols ширина поля в символах.

Внешний вид тега:
Внешний вид тега textarea

<button>

Позволяет выводить комбинированные с текстом и изображением.

<button><img src="image.png" alt="Кнопка с рисунком и текстом" />&nbsp;Кнопка с рисунком и текстом</button>

Внешний вид тега:
Внешний вид тега button

<fieldset>

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

<fieldset>
	<legend>чекеры</legend>
	<input type="radio" name="radio" value="мужской" checked="checked"/>
	<input type="radio" name="radio" value="женский"/><br /><br />
	<input type="checkbox" name="checkbox1" value="привет1"/>
	<input type="checkbox" name="checkbox2" value="привет2"/>
</fieldset>

Внешний вид тега:
Внешний вид тега fieldset

<legend>

Предназначен для вывода названия тега fieldset внутри которого содержится.

<label>

Предназначен для вывода названия элемента формы, все предыдущие примеры просто выводили элементы формы и понять для чего нужен данный элемент не представляется возможным. Для более дружелюбного отношения с юзеров предназначен этот тег.

Существует два способа использования тега. Первый — привязывание идентификатора id элемента к атрибуту for тега label. При втором способе элемент формы оборачивается тегом label. Еще характеризуется тем, что при клике на лейбу, элемент к которому она привязана получает фокус.

<label for="textId">Приветствие</label><input id="textId" type="text" name="text" value="привет"/><br /><br />
<label>пароль<input type="password" name="password" value="привет"/></label>

Внешний вид тега:
Внешний вид тега label

Список используемой литературы

  1. Мои знания
  2. http://www.nbuv.gov.ua/books/19/html40/interact/forms.html
  3. http://htmlbook.ru

Статья просмотренна 127658 раз, зашло посетителей 20492

  

Облако тегов

cli csv dump events form Kohana locale models MySQL mysqldump orm PHP tools trigger validate газ газовый счетчик итоги кеширование переменные

Облако тегов плагина WP Cumulus для WordPress требует для просмотра Flash Player 9 или выше.

Я на твиттере!

  • у твиттера тоже бывают перерывы...

Календарь

Октябрь 2024
Пн Вт Ср Чт Пт Сб Вс
« Июл    
 123456
78910111213
14151617181920
21222324252627
28293031  

Сейчас на сайте