Check personal ID code in Symfony 1.4 sfValidatorIsikukood

Sorry, this entry is only available in Russian. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

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

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

Leave a Reply