Проверка персонального кода в Synfony 1.4 sfValidatorIsikukood

Пример создания собственного валидатора персонального кода в 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)

Вы знаете, для меня это не просто первый опыт создания своего валидатора, но и первое воплощение проверки кода в реальном проекте. Но самое главное, что эта тема — первая тема нового блога. Тройное браво!

en_USEnglish