![]() |
Биллинговая система NoDeny. Программирование |
Информация для разработчиков
Программирование веб-админки NoDeny (в разработке...)
Основные служебные подпрограммы находятся в calls.pl. Обратите внимание, что некоторые подпрограммы используют глобальные переменные! Так очень часто используется глобальная переменная $dbh.
sql_select_line предназначена для выборки одной строки из таблицы БД.
Вход:
0 - ссылка dbh
1 - sql-запрос
2 - [комментарий]
3 - [скрытый запрос]
Обязательны только параметры 0 и 1. Комментарий будет выведен главному администратору в специальной области где отображаются все выполняющиеся sql-запросы. Если у администратора нет прав на просмотр sql-запросов либо он отключил их вывод, то комментарий игнорируется. Если комментарий выводится, то перед sql-запросом. Если параметр 3 установлен, то вместо реального sql-запроса выводится этот (3й) параметр. Предназначено для скрытия запросов, в которых участвуют пароли. Если комментарий равен 0 (символ `ноль`), то все данные по запросу будут выведены мелким шрифтом в одну строку.
Возврат:
0 - ссылка fetchrow_hashref или false, если ошибка либо пустая выборка
Пример:
$p=&sql_select_line($dbh,"SELECT unix_timestamp()",'Получим время на сервере БД'); &Error("Не удалось получить время из БД!") unless $p; $t=$p->{'unix_timestamp()'};
Либо:
$p=&sql_select_line($dbh,"SELECT passwd FROM xxx WHERE id=5",0,'Получим пароль, запрос не показываем'); $passwd=$p? $p->{passwd} : '12345';
Обратите внимание, что sql_select_line предназначен для выборки только одной строки. Для выбора нескольких строк используйте:
sql
Вход: тоже, что и у sql_select_line
Выход: ссылка на ->execute или false, если ошибка
Пример:
$sth=&sql($dbh,"SELECT * FROM users",'Получим список всех клиентов'); while ($p=$sth->fetchrow_hashref) { $OUT.="ip: $p->{ip}<br>"; }
sql_do предназначена для выполнения запросов обновления (INSERT, UPDATE, DELETE).
Вход: тоже, что и у sql_select_line.
Выход: количество обновленных строк либо ноль, если ошибка.
Обратите внимание, что количество обновленных строк может быть равно нулю, но это не будет означать ошибку, т.е. условию будет соответствовать 0 строк. Эта ситуация разруливается стандартным методом (придумано не в NoDeny):
если ошибки нет и обновлено 0 строк, то возвращается значение, которое НЕ является нулем, однако при сравнении РАВНО нулю. Возможно, это выглядит как хак, однако это вполне неормально для perl.
Пример:
$rows=&sql_do($dbh,"UPDATE users SET balance=balance-1 WHERE id=1 LIMIT 1"); &Error('Баланс не обновлен, проблема с БД.') unless $rows; &Error('Баланс не обновлен - клиент с id=1 не найден в БД!') if $rows<1; &OkMess('Баланс обновлен. Все ок');
Комментарии:
Хотя поле id таблицы users является уникальным, мы использовали LIMIT 1. Это является стилем автора, который вполне логично обосновывается: операции обновления/удаления являются относительно опасными, поскольку ошибись программист и не укажи условие или укажи его неправильно - есть риск обновить/удалить всю таблицу. В данном случае, при ошибке мы получим обновление только одной строки.
Условие unless $rows выполняется, когда $rows будет = 0. Когда обновлено 0 строк, в $rows содержится значение не 0, поэтому это условие не будет срабатывать. С другой стороны, при стравнении с единицей $rows будет являться нулем. Т.е. будет выполнено условие $rows<1.
Подпрограммы-фильтры.
Фильтры предназначены для отсеивания или замены специальных символов в передаваемых переменных для того чтобы исключить вредное либо непрогнозируемое действие этих спецсимволов.
С NoDeny существует 2 вида фильтров: для mysql и для web.
Для web:
Filtr_out фильтрует символы, которые являются управляющими для html.
Применять всегда, когда необходимо вывести какие-либо данные в html-страницу клиента.
Пример:
$p=&sql_select_line($dbh,"SELECT fio FROM user WHERE id=5"); &Error('Ошибка получения данных клиента') unless $p; $OUT.='Фамилия клиента: '.&Filtr_out($p->{fio});
Если не произвести фильтрацию, то после того, как любопытный диспетчер даст клиенту имя «<h1>Иванов</h1>», мы получим вывод его имени большими буквами. Это простейший пример, а можно еще и javascript ввести...