Перейти к содержимому

Фото
- - - - -

Валидатор форм (PHP)


  • Вы не можете создать новую тему
  • Please log in to reply
41 ответов в этой теме

#31 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 09 Декабрь 2007 - 14:02

Да, надо будет глянуть на чудо инженерной мысли. :)
  • 0

#32 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 10 Декабрь 2007 - 18:20

Вчера натолкнулся на очень неприятный косяк, попалась форма с несколькими группами полей, каждая группа в своём массиве, а валидатору никак было не объяснить из какого массива брать какие значения, пришлось сделать поддержку таких форм, получилось довольно красиво ;) Нет времени пока оформить примерчик... Сам код вряд ли о чём-то скажет)
  • 0

#33 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 10 Декабрь 2007 - 20:18

Ты делись давай ) А мы уже и глянем )
  • 0

#34 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 10 Декабрь 2007 - 23:40

Приложен исходник валидатора 2 класса, очень краткий пример использования:

<?php
Пример формы:

$_POST = Array(
	[comment] => Комментарий
	[register] => Array(
		[name] => Имя
		[company] => Фирма
		[address] => Адрес
		[city] => Город
		[indeks] => Индекс
		[phone] => Телефон
		[email] => Мыло
		[password] => Пароль
		[password2] => Повтор пароля
	)
)

Нет времени делать примеры, вот кое-что накорябал, классы все прокоментированы почти до каждой строки

// Пример использования
$validator = new MultiformValidator();

if ( $validator->hasValidated() )
{
	// Форма прошла проверку...
}

/**
 * Валидация нескольких форм в одной
 */
class MultiformValidator extends FormValidator
{
	protected function configure()
	{
		// Тут указываем какие формы будем использовать
		$this->addForm( 'register' );
	}

	protected function execute()
	{
		// По-умолчанию так же обрабатываются все поля 1го уровня
		$this->addElement( 'comment' ) // Комментарий
			->addFilter( 'maxLenght', null, array( 100 ) ); // Макс. длина поля 100 символов
	}

	protected function executeRegister()
	{
		$this->addElement( 'name' )
			->setRequired();

		$this->addElement( 'company' );

		$this->addElement( 'address' )
			->setRequired();

		$this->addElement( 'city' )
			->setRequired();

		$this->addElement( 'indeks' ) // тут просто пример своего правила
			->setRequired()
			->addCallback( 'Indeks', 'Индекс должен состоять только из цифр' );

		$this->addElement( 'phone' );

		$this->addElement( 'email' )
			->setRequired()
			->addCallback( 'email', 'Неверный формат Email адреса' )
			->addCallback( 'hasRegisteredEmail', 'Такой Email уже зарегистрирован' );

		$this->addElement( 'password' )
			->setRequired()
			->addCallback( 'lenght', 'Длина пароля может быть от 6 до 12 символов', array( 6, 12 ) );

		$this->addElement( 'password2' )
			->addCompare( 'password', 'Пароли должны совпадать' );
	}

	public function validateIndeks( $indeks )
	{
		if ( ! is_numeric( $indeks ) )
		{
			return false;
		}
	}

	public function hasRegisteredEmail( $email )
	{
		if ( емайл не зарегистрирован в системе )
		{
			return false;
		}
	}
}

P.S. всё очень гениально просто, никаких выдуманых сложностей. Гибкость реализуется только за счёт своих callbackRaw функций (что это такое - в комментариях FormValidatorElement). Есть в планах сделать так, что форма будет задаваться не как просто набор имён полей, а так же как тип инпут, селект и т.п. Правда, это может свести на нет всю текущую простоту...

Прикрепленные файлы


Сообщение изменено: Setor (14 Декабрь 2007 - 15:34 )

  • 0

#35 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 13 Декабрь 2007 - 17:45

Я наверно тупой, но я так и не вкурил, как оседлать этого зверька)))
  • 0

#36 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 14 Декабрь 2007 - 18:30

Я наверно тупой, но я так и не вкурил, как оседлать этого зверька)))

Да нет, просто использовать чужие разработки всегда сложно... Я иногда заглядываю в свой старый код и сомневаюсь, что это я его когда-то писал. Настолько сложные алгоритмы, проверки, формулы какие-то и сортировки, диву даёшься ;) Чтобы разобраться в таком коде либо нужен комментарий каждой строчки, либо пару часов на дебаггинг (пошаговый Debug в Zend Studio).

Основная суть этих классов заключается лишь в том, что:
1) Они знают какие входящие переменные им нужны
2) Они знают как их отфильтровать
3) Они знают какую callback функцию к ним применить
4) Они оставляют результат проверки и сообщения. Каждый элемент формы знает о том, был ли он проверен и есть ли у него какие-то сообщения об ошибках.

Например, можно отрисовать форму через шаблонизатор, выделив ошибки:
/*
 * @var $validator FormValidator
 * @var $formName Имя формы (если нет массивов в $_POST, оставить пустым)
*/
private function fillForms( $validator, $formName = '' )
{
	foreach ( $validator->getElements( $formName ) as $element )
	{
		$this->templateEngine->assign( $formName . '_' . $element->getName(), $element->getValue( true ) ); // getValue( true ) = htmlspecialchars( $value )

		if ( ! $element->hasValidated() ) // Если проверка поля не прошла
		{
			// Поля с ошибками выделяем цветом
			$this->templateEngine->( $formName . '_' . $element->getName() . '_error', ' style="background-color: red"' );

			// Если есть сообщения об ошибках, тоже выводим
			if ( $element->hasMessages() )
			{
				$this->templateEngine->( $formName . '_' . $element->getName() . '_message', '<br/>' . $element->getFirstMessage() );
			}
		}
	}
}

Основная мощь заключается в callback функциях, которые могут делать что угодно - обращаться к БД или на луну за инфой, производить какие-то вычисления или проверки. И так же у них есть возможность получить доступ к другим полям формы, т.е. можно строить зависимости.



P.S. я там обновил классы, в одном из них закралась ошибка, стояла неправильная проверка (вместо true проверяла false), из-за этого не выводились мессаги.

P.S. И ещё объект можно передать в Smarty и можно нарисовать очень красивый шаблончег ;)
  • 0

#37 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 14 Декабрь 2007 - 22:22

А форму то как рисовать, не понятно .. самому писать ХТМЛ код, там .... <form method="POST"><input type... и так далее ..или что ? )) Зачем нужно вот это - $_POST = Array(
[comment] => Комментарий
[register] => Array(
[name] => Имя
[company] => Фирма
[address] => Адрес
[city] => Город
[indeks] => Индекс
[phone] => Телефон
[email] => Мыло
[password] => Пароль
[password2] => Повтор пароля
)
) ? ))) Постоянно ругается Fatal error: Class 'MultiformValidator' not found in тра ля ля .... уже всю голову сломал, ничего не выходит (( Можешь прислать запакованный пример как у тебя сделано ... ну, чтобы всё собрано было, а то ещё долго все сидеть будем и не фтыкать )

Сообщение изменено: Диверсант (14 Декабрь 2007 - 22:35 )

  • 0

#38 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 14 Декабрь 2007 - 23:02

Диверсант, ты меня озадачил :)

1) Это был пример массива, который получается после отправки формы. Саму форму мне было лень рисовать.

2) Сначала надо объявить класс, а потом его инициализировать. Т.е. суёшь его например, в отдельный файл и инклудишь + инклудишь ещё два приложенных класса. Это элементарно же) Пример прислать не могу, т.к. у меня всё зашито в приложении и я не могу из него выдрать.

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

Следующим этапом развития валидатора будет задание типов полей. Например, есть у нас форма с radio кнопками, на одну из них тыркнули, шаблонизатор должен её будет сам пометить. Т.е. форма будет полностью зашита в класс. И вроде как это всё реализовано в Pear Quick Form, но я его смотрел, так нифига и не понял :)

Диверсант, может есть смысл взять что-то более приспособленное для обычного народа?
  • 0

#39 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 15 Декабрь 2007 - 00:26

Setor, ну я вчера ради интересна поискал в нете, но нашёл всякий хлам .. :) Может плохо искал ) Хм, как я понял из твоих объяснений, для работы всего этого надо как бы 3 фаила проинклюдить ? Я вот просто брал вот твою тестовую форму .. в нее инклюдил 2 этих .class.php файла, но он орал на ошибку, хотя всё на месте. Ладно ) буду искать что-то другое)

Сообщение изменено: Диверсант (15 Декабрь 2007 - 00:29 )

  • 0

#40 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 15 Декабрь 2007 - 00:57

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

Что там за ошибка у тебя такая? Сначала класс надо было определить, а потом его инициализировать)

Ладно, уговорил. Вот пример.

Ключевые моменты сюда, остальное я уже писал и оно в архиве

// Пример использования
$validator = new MultiformValidator();

if ( $validator->hasValidated() )
{
	// Форма прошла проверку...
	print_r( $validator->getElements() );
}
else
{
	print_r( $validator->getMessages() );
}

?><hr>

<table width="100%" border="0">
<form method="POST">

<?php

foreach ( $validator->getElements( 'register' ) as $element )
{
	echo '<tr><td width="120">';
	echo ucfirst( $element->getName() );
	echo '</td><td>';
	echo '<input type="text" size="40" name="register[' . $element->getName() . ']" value="' . $element->getValue(1) . '"' . ( $element->hasValidated() ? '' : ' style="background-color: yellow"' ) . '><br/>';
	echo '</td></tr>';
}	

?>
<tr>
	<td>Комментарий</td>
	<td><textarea name="comment" rows = 10 cols = 60><?=$validator->getValue( 'comment', '' )?></textarea></td>
</tr>
<tr>
	<td> </td>
	<td><input type="submit"></td>
</tr>
</table>
</form>

P.S. если будут ошибки, что ф-ция не найдена filter_var, а она есть по-дефолту только в пхп 5.2, как я уже говорил. Нужно из правил убрать фильтр проверки мыла. Т.е.
$this->addElement( 'email' )
	 ->setRequired()
	 //->addCallback( 'email', 'Неверный формат Email адреса' )
	 ->addCallback( 'hasRegisteredEmail', 'Такой Email уже зарегистрирован' );

Вот так оно должно выглядеть: http://setor.net/validator/ (если у меня комп включен, ссылка будет работать)

Прикрепленные файлы

  • Прикрепленный файл  validator.zip   6,21К   7 Количество загрузок

Сообщение изменено: Setor (15 Декабрь 2007 - 00:59 )

  • 0

#41 .NET

.NET
  • Постоялец
  • 3 511 сообщений

Отправлено 15 Декабрь 2007 - 12:05

Фух ) Теперь работает )))) Очень хорошая система однако) Очень) Вот только не заметил, есть ли функция проверки на минимальное значение. Допустим мне надо, чтобы значение в поле было не менее 3 знаков, конечно можно поставить - ->addCallback('lenght', 'Минимум 3 символа!', array( 3, 100) ); , а то вот maxLenght есть, а min нету ) надо доделать ) А так, вообще замечтально )

Сообщение изменено: Диверсант (15 Декабрь 2007 - 15:06 )

  • 0

#42 Setor

Setor
  • Постоялец
  • 1 890 сообщений
  • Откуда:Эстония, Таллин

Отправлено 18 Декабрь 2007 - 21:38

Вот только не заметил, есть ли функция проверки на минимальное значение. Допустим мне надо, чтобы значение в поле было не менее 3 знаков, конечно можно поставить - ->addCallback('lenght', 'Минимум 3 символа!', array( 3, 100) ); , а то вот maxLenght есть, а min нету ) надо доделать ) А так, вообще замечтально )

Я туда вложил только 1 или 2 функции проверки... ;) Валидатор тем и замечателен, что позволяет легко внедрять практически любой необходимый функционал. Чтобы не юзать постоянно addCallback, можно написать делегирующие методы, которые сами будут вызывать addCallback. Типа ->minLenght( 'Минимум 3 символа!', 3 ). Для частоиспользуемых функций я так и делаю.

ЗЫ: Диверсант, лучше не пользуйся исправлением, когда хочешь что-то добавить к 1му сообщению, иначе не приходит 2й раз извещение на мыло.

Народ, может кто знает ещё о каких-то популярных/удобных/функциональных похожих решениях?
  • 0