Проверка персонального кода в Synfony 1.4 sfValidatorIsikukood
[:ru]Пример создания собственного валидатора персонального кода в Symfony.
В одном проекте потребовалось использовать эстонские личные коды (isikukood), которые даются каждому жителю этого государства и имеют возможность быть проверенными на валидность без запросов в какие-либо регистры.
Код содержит 11 цифр, 7 из которых обозначают пол, год, месяц и дату рождения, три последующие цифры – порядковый номер, и последняя цифра контрольная сумма. Ей то я и займусь.
Формула для вычисления контрольной суммы известна благодаря горячим обсуждениям в этой теме на forum.ee. Пожалуй, я использую свой вариант, так как мне он наиболее симпатичен. Кто бы сомневался ;)
В Symfony классы валидаторов имеют определённую структуру. Я, чтобы не морочаться долго, беру валидатор sfValidatorString, копирую в папку lib/validator и начинаю его изменять. Удаляю лишнее – проверку длины… Стойте-ка, длина строки здесь важна, ведь все цифры кода учавствуют в подсчёте. Пожалуй стоит просто расширить класс sfValidatorString новым функционалом, добавив проверку контрольной суммы. Так и поступаю.
Создаю файл lib/validator/sfValidatorIsikukood.class.php
class sfValidatorIsikukood extends sfValidatorString {
Конфигурация. Устанавливаю параметры max_length и min_length равному длине личного кода чтобы не передавать эти параметры каждый раз из форм. Так же добавляю сообщение об ошибке проверки контрольной суммы.
protected function configure($options = array(), $messages = array()) { parent::configure( $options, $messages ); $this->addOption('max_length', 11); $this->addOption('min_length', 11); $this->addMessage('not_valid_ik', '"%value%" is not valid personal code.'); }
Теперь, переопределяю главный метод, выполняющий проверку. Сначала выполнится сценарий sfValidatorString, потом сверится контрольная сумма:
protected function doClean($value) { parent::doClean($value); if ( $value[10] != $this->getIsikukoodCC($value) ) throw new sfValidatorError($this, 'not_valid_ik', array('value' => $value)); return $value; }
Собственно, функция подсчёта контрольной суммы:
protected function getIsikukoodCC($i) { $s = $i[0]*1+$i[1]*2+$i[2]*3+$i[3]*4+$i[4]*5+$i[5]*6+$i[6]*7+$i[7]*8+$i[8]*9+$i[9]*1; if ( ( $s %= 11 ) < 10 ) return $s; $s = $i[0]*3+$i[1]*4+$i[2]*5+$i[3]*6+$i[4]*7+$i[5]*8+$i[6]*9+$i[7]*1+$i[8]*2+$i[9]*3; if ( ( $s %= 11 ) < 10 ) return $s; return 0; } }
Пробую применить валидатор к полю isikukood своей формы:
$this->setValidator( 'isikukood', new sfValidatorIsikukood( array('required'=> true) ) );
Работает! Валидатор возвращает ошибки в случае:
- если код не введён (required)
- если он не 11 символов длиной (max_length, min_length)
- если контрольная сумма не совпадает (not_valid_ik)
Вы знаете, для меня это не просто первый опыт создания своего валидатора, но и первое воплощение проверки кода в реальном проекте. Но самое главное, что эта тема — первая тема нового блога. Тройное браво![:]