Проверка персонального кода 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)
Вы знаете, для меня это не просто первый опыт создания своего валидатора, но и первое воплощение проверки кода в реальном проекте. Но самое главное, что эта тема -- первая тема нового блога. Тройное браво!
