Tuesday, October 28, 2008

PHP, Excetion облегчают обработку форм. Ностальгия блин.

Теряя время в интернете на поиск интересных блогов связанных или с php или с веб программированием так, чтобы я мог увидеть в этом что то интересное для себя, набрел на блог http://alt-f4.ru. Поковырял статьи, особо сказать ничего не могу, кто-то делиться своим опытом, просто времена когда мне бы его опыт пригодился бы остались в прошлом.

В итоге набрел на статью "Авторизация посетителей на PHP", в которой по шагам, потихонечку написано как кому чего делать чтобы у него было счастье.

Ну а теперь самое интересное, наткнулся на код обработки формы.


if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$rLogin = trim($_POST['rLogin']);
$rPass = trim($_POST['rPass']);
$rPass2 = trim($_POST['rPass2']);
$rEmail = trim($_POST['rEmail']);
if ($rLogin == '') {
die("Поле 'Логин' не заполнено\n");
// Логин может состоять из букв, цифр и подчеркивания
}elseif (!preg_match("/^\w{3,}$/", $rLogin)) {
die("В поле 'Логин' введены недопустимые символы\n");
}
if ($rEmail == '') {
die("Поле 'E-mail' не заполнено\n");
// Проверяем e-mail на корректность
}elseif (!preg_match("/^[a-zA-Z0-9_\.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,6}$/", $rEmail)) {
die("Указанный 'E-mail' имеет недопустимый формат\n");
}
if ($rPass == '' || $rPass2 == '') {
die("Поле 'Пароль' не заполнено\n");
}elseif($rPass !== $rPass2) {
die("Поля 'Пароль' и 'Повтор пароля' не совпадают\n");
// Пароль может состоять из букв, цифр и подчеркивания
}elseif(!preg_match("/^\w{3,}$/", $rPass)) {
die("В поле 'Пароль' введены недопустимые символы\n");
}
// В базе данных у нас будет храниться md5-хеш пароля
$mdPassword = md5($rPass);
// А также временная метка (зачем - позже)
$time = time();
// Устанавливаем соединение с бд(не забудьте подставить ваши значения сервер-логин-пароль)
$link = mysql_connect('localhost', $dbuser, $dbpass);
if (!$link) {
die("Не могу соединиться с базой данных");
}else {
// Выбираем базу данных
mysql_select_db('authorize', $link);
// Записываем в базу (не используем addslashes - экранировать нечего)
mysql_query("INSERT INTO users (login, pass, email, timestamp)
VALUES ('$rLogin','$mdPassword','$rEmail',$time)",$link);
if (mysql_error($link) != "") {
die("Пользователь с таким логином уже существует, выберите другой\n");
}
echo "Юзер добавлен\n";
mysql_close($link);
}
}
?>


В общем, про использование прямых запросов сразу молчим, но что наглядно, форма из 4-х полей, а уже 3 вложенных условия, да и вообще логика не простая.

Самое что главное, если заменить способы валидации, то к своему стыду получается что я писал подобный код не так давно. И только натолкнувшись на совсем сумасшедшую логику, прикрутил Exceptions и чудо
1. Объем кода уменьшился в два раза.
2. Количество вложенных условий сократилось до 1-го
3. Ошибки стало проще выводить.

Ну и применительно к данному коду, применя преобразовния не меняющие логику получим что то вроде. .


class DbException extends Exception {};

if ($_SERVER['REQUEST_METHOD'] != 'POST')
{
try
{
foreach ( array('rLogin' => 'Логин' , 'rPass' => 'Пароль' , 'rPass2' => 'Повторный пароль', 'rEmail' => 'E-mail' ) as $val => $fieldName)
{
if ( isset($_POST[$val] ) )
$val = trim($_POST[$val]); //create rLogin, rPass, rPass2, rEmail variables
else
throw new Exception("Поле $fieldName не заполнено\n");
}

if (!preg_match("/^\w{3,}$/", $rLogin))
throw new Exception("В поле 'Логин' введены недопустимые символы\n");

if (!preg_match("/^[a-zA-Z0-9_\.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,6}$/", $rEmail))
throw new Exception("В поле 'Логин' введены недопустимые символы\n");

if($rPass !== $rPass2)
throw new Exception("Поля 'Пароль' и 'Повтор пароля' не совпадаютn");

if(!preg_match("/^\w{3,}$/", $rPass))
throw new Exception("В поле 'Пароль' введены недопустимые символы\n");

$mdPassword = md5($rPass);
// А также временная метка (зачем - позже)
$time = time();
// Устанавливаем соединение с бд(не забудьте подставить ваши значения сервер-логин-пароль)
$link = mysql_connect('localhost', $dbuser, $dbpass);
if (!$link)
throw new DbException("Не могу соединиться с базой данных");
// Выбираем базу данных
mysql_select_db('authorize', $link);
// Записываем в базу (не используем addslashes - экранировать нечего)
mysql_query("INSERT INTO users (login, pass, email, timestamp) VALUES ('$rLogin','$mdPassword','$rEmail',$time)",$link);// поле timestamp можно сделать чтобы по умолчанию подставлялось базой, такие вещи лучше перекладывать на базу.
if (mysql_error($link) != "")
DbException("Пользователь с таким логином уже существует, выберите другой\n");
echo "Юзер добавлен\n";
mysql_close($link);
}
catch (DbException $e)
{
die("DB ERROR: " . $e->getMEssage());
}
catch ( Exception $e)
{
die( "Form validation error: ". $e->getMessage());
}
}
?>

В итоге.

  • Кода меньше.

  • Читается проще.

  • Вывод ошибок в одном месте.

  • При необходимости разные виды ошибок ловим в нужных нам местах.



2 comments:

Станислав said...

Честно говоря не представляю, как с применением только исключений(без менеджера) вытащить все ошибки формы. Поэтому используем intercepting chain

Unknown said...

1. Понятно что таким образом (при помощи exceptions) все ошибки разом не получишь.

2. Это был просто пример, рефакторинга что ли, в оригинале стояли die, я просто показал как можно код упростить (ну детство что ли заиграло :)

3. Почитал про фильтры цепочки. Ну про то что формы так обрабатывают я не знал, хотя можно было бы предположить я видел фреймворки где делался упор на последовательность фильтров.

Такие вещи мне не очень нравятся, у меня религия другая :) По идеологии похоже, хотя многие бы сказали код не "академически красивый " :)

Хотел написать как делаем мы, (это уже третий вариант форм который я начал использовать) Но мне сказали что таг pre идет нафик

положил если интересно кода 20 строк сюда

 
Каталог сайтов, Добавить сайт