Во многих веб приложениях необходимо хранить разнообразные настройки. Например, настройки почтовых рассылок в социальных сетях или на форуме. С точки зрения хранения данных одним из распространенных способов является сохранение настроек в поле типа SET. Такой способ удобен для хранения двух состояний каждой настройки (включено/выключено). Но в некоторых случаях нужно сохранять несколько значений. Пример из социальных сетей: настройка приватности “Кто может видеть мой email?” - здесь возможны варианты:
- все (2)
- только мои друзья (1)
- никто (0)
В данном случае настройки можно хранить в виде строки чисел, где каждый символ отвечает за определенный пункт настроек. Например строка “019910” - в ней первый символ отвечает за настройку “Кто может видеть мой email?”. В данном примере первый символ равен “0″, т.е. никто не может видеть email пользователя.
Ну вот, хотел написать об MySQL функции, а получилось вступление по другой теме :-)
Перейдем к примерам работы со строками в MySQL.
MySQL предоставляет целый ряд функций для работы со строками. Для замены символа (или подстроки) используется функция INSERT:
INSERT(str, pos, len, newstr) - возвращает строку str, где подстрока, которая начинается с pos и имеет длину len, заменена строкой newstr
Пример:
SELECT INSERT(’Zend Framework’, 1, 4, ‘Symfony’)
Такой запрос заменяет подстроку “Zend” на “Symfony” и в результате получается “Symfony Framework”.
Очень важно помнить, что в MySQL индексы строк начинаются с 1, а не с 0!
Таким образом, для замены символа в строке (на примере настроек приватности):
UPDATE `users` SET `privacy` = INSERT(`privacy`, 1, 1, ‘2′)
Данным запросом меням настройку приватности для email. Исходная строка принимает значение “219910″ - это значит что email доступен для просмотра всем.
Кажется, пора идти домой уже… :-)
Очень удобная вещь - Zend_Form. Данный компонент предоставляет множество возможностей, таких как фильтрация и валидация данных формы. Zend_Form имеет ряд собственных валидаторов и фильтров, но он достаточно гибок, и есть возможность создавать свои классы для валидации.
Рассмотрим на примере создание собственного валидатора для формы регистрации.
Возьмем простейшую форму для регистрации, с минимальным набором полей:
- логин
- пароль
- пароль повторно
Требования к полям:
- Логин - обязательное поле, строка из цифро-буквенных символов длиною от 3 до 15 символов, уникальное.
- email - обязательное поле, имеет правильный формат, уникальное.
- Пароль - обязательное поле, строка из любых символов, не короче 6 символов
- Пароль повторно - поле должно совпадать с полем ‘пароль’.
Исходя их требований, можно сделать вывод, что нам нужно написать 3 собственных валидатора:
- Проверка уникальности логина.
- Проверка уникальности email.
- Проверка совпадения паролей.
Для создания custom validator, нужно наследовать класс от абстрактного Zend_Validate_Abstract, и реализовать в нем метод isValid.
В своих проектах валидаторы я храню в директории models/validator.
Создание валидатора уникальности логина
Создаем новый файл models/validator/UniqueNickname.php
<?php class Validator_UniqueNickname extends Zend_Validate_Abstract { const NOT_UNIQUE = ‘notUnique’; /* * Сообщения об ошибках валидации */ protected $_messageTemplates = array( self::NOT_UNIQUE => “Username ‘%value%’ has already been taken” ); public function isValid($value) { $this->_setValue($value); $isValid = true; /* * Метод User::checkLogin проверяет используется ли в базе такой логин, * если да, то возвращает user id */ $userId = User::checkLogin($value); if ($userId) { $this->_error(self::NOT_UNIQUE); $isValid = false; } return $isValid; } }
Создание валидатора уникальности email
Создаем новый файл models/validator/UniqueEmail.php
<?php class Validator_UniqueEmail extends Zend_Validate_Abstract { const NOT_UNIQUE = ‘notUnique’; protected $_messageTemplates = array( self::NOT_UNIQUE => “Email ‘%value%’ has already been taken” ); public function isValid($value) { $this->_setValue($value); $isValid = true; $userId = User::checkEmail($value); if ($userId) { $this->_error(self::NOT_UNIQUE); $isValid = false; } return $isValid; } }
Создание валидатора для паролей
С этим валидатором дела обстоят интереснее. Создаем новый файл models/validator/EqualValues.php.
<?php class Validator_EqualValues extends Zend_Validate_Abstract { const NOT_EQUAL = ‘notEqual’; protected $_messageTemplates = array( self::NOT_EQUAL => ‘Passwords are not equal’ ); protected $_contextKey; public function __construct($key) { $this->_contextKey = $key; } public function isValid($value, $context = null) { if (is_array($context)) { if (isset($context[$this->_contextKey]) && ($value === $context[$this->_contextKey])) { return true; } } if ($value === $context) { return true; } $this->_error(self::NOT_EQUAL); return false; } }
Форма регистрации
Теперь создаем непосредственно саму форму регистрации (models/form/Register.php)
<?php class Form_Register extends Zend_Form { public function __construct($options = null) { parent::__construct($options); $this->setAction(HOME_URL . ‘register/’) ->setMethod(‘post’); $login = new Zend_Form_Element_Text(‘login’); $login->setLabel(‘Логин’) ->setRequired(true) ->addFilter(‘StripTags’) ->addFilter(‘StringTrim’) ->addFilter(‘StringToLower’) ->addValidator(‘StringLength’, true, array(‘min’ => 3, ‘max’ => 15)) ->addValidator(‘alnum’) ->addValidator(new Validator_UniqueNickname()) ; $email = new Zend_Form_Element_Text(‘email’); $email->setLabel(‘email’) ->setRequired(true) ->addFilter(‘StripTags’) ->addFilter(‘StringTrim’) ->addFilter(‘StringToLower’) ->addValidator(new Zend_Validate_EmailAddress()) ->addValidator(new Validator_UniqueEmail()) ; $password = new Zend_Form_Element_Password(‘password’); $password->setLabel(‘Пароль’) ->setRequired(true) ->addValidator(‘StringLength’, true, array(‘min’ => 6)) ; $passwordAgain = new Zend_Form_Element_Password(‘passwordAgain’); $passwordAgain->setLabel(‘Повторите пароль’); // Валидатор для совпадения паролей $passwordAgain->addValidator(new Validator_EqualValues(‘password’)) ->setAllowEmpty(false); $submit = new Zend_Form_Element_Submit(’submit’); $submit->setLabel(‘Ok’); $this->addElements(array($login, $email, $password, $passwordAgain, $submit)); } }
При добавлении валидатора для паролей нужно вызывать метод setAllowEmpty со значением false. Это делается для того чтобы валидатор паролей срабатывал при пустом значении “Пароль повторно”.
Сам процесс регистрации не входит в рамки данной статьи, возможно позже напишу продолжение данной статьи.