Создание встроенного модуля CMS. Часть 3
Статья подразумевает, что вы уже прочитали первую часть.
Рассматривается вопрос разделения модуля на часть для посетителей и часть для администратора сайта.
Статья пишется по горячим следам разработки модуля гостевой книги. Поэтому сразу сделаем допущение, что внутреннее имя у него guestbook.
Содержание
Самый простой вариант
Вывод разных строк в зависимости от того, сайт это или админка.
sub guestbook() { if ( defined param('edt') ) { print "Hello, admin interface!"; } else { return "Hello, site!"; } }
Обратите внимание, для сайта всё ещё действует правило, обязывающее возвращать данные (return). А в админке следует использовать print. Разумеется, это никак не мешает накапливать данные в переменных и под конец выдать их в нужном порядке.
Собственная таблица для произвольных данных
Сделаем таблицу:
CREATE TABLE GUESTBOOK ( ID INTEGER NOT NULL, NAME VARCHAR(128), TEXT BLOB SUB_TYPE 1 SEGMENT SIZE 80, POST_DATE TIMESTAMP, published SMALLINT DEFAULT 0, OWNER INTEGER NOT NULL );
Пройдёмся по полям:
- ID — идентификатор объекта, Это общая рекомендация проектирования баз данных, рекомендуем всегда создавать его для любых, это намного упростит вам дальнейшую разработку.
- NAME, TEXT, POST_DATE — это уже произвольные поля, которые могут быть какими угодно для потребностей вашего нового модуля. Для простейшего примера гостевой книги их будет достаточно.
- published — признак опубликованности. Для модуля новостей это может быть признаком черновика; для навигации это может быть галочкой, включающей пункт в меню; для гостевой книги это будет признак одобрения модератором. 0 будет означать "сообщение на рассмотрении", 1 — "одобрено к показу на сайте".
- OWNER — владелец сайта. 6 у нас всегда школльный сайт, остальное — блоги. Об этом важно помнить при разработке всех модулей, которые будут писать и читать из базы. Вам не нужно каждый раз выяснять владельца, CMS уже заботится об этом. Когда выполняется модуль, глобальная переменная
$owner
уже содержит какое-то число, равное идентификатору авторизованного пользователя в админке либо автора сайта. Вам остаётся только использовать его для вставки в базу данных для этого владельца или выбирать из базы данные только для такого владельца. Таким образом реализуется хранение данных для сайта и блогов в одной таблице. Ниже будет приведён пример использования владельца. $owner всегда определён, потому что выполнение модуля в режиме админки без авторизации невозможно, выполнение модуля на сайте без определения владельца тоже невозможно (будет выдана ошибка 404, ни один модуль не выполнится).
Добавление данных
Форма ввода сообщения в самом простом случае выглядит так:
<form class="guestbook" method="post"> Имя: <input type="text" name="name"> Текст: <textarea name="text"></textarea> <button type="submit">Отправить</button> </form>
Пример реакции на отправку этой формы:
my $name = param('name'); my $text = param('text'); sqlb("INSERT INTO GUESTBOOK (NAME, TEXT, POST_DATE, published, owner) VALUES (?, ?, NOW()), 0, $owner", $name, $text );
Отступление о безопасности
Забрать из запроса с помощью функции param() и сразу использовать их небезопасно. В этом цикле статей используется простейший код, не содержащий проверок на корректность данных. Для ознакомления с методами защиты данных настоятельно рекомендуется прочитать статью Защита веб-приложений на Perl.
В портале уже есть встроенные методы проверки данных. Например, прочитайте функции sec_* в common.pl.
Использовать их просто:
# обязательная проверка my $id = param('id'); sec_gt0($id); # проверка параметра, которого может и не быть my $opt = param('opt'); sec_gt0($opt) if defined($opt);
В common.pl с версии 5.2 доступна функция, упрощающая безопаное чтение данных для записи в базу и последующего показа на сайте:
# пример использования my $a = param_dexss_lim('a', 64);
Смысл: прочитать параметр по имени a, отразить XSS, взять не более 64 символа.
Чтение данных
my $query = sqlp("select * from guestbook where published = 1 and owner = $owner"); # sqlp выполняет DBI::prepare, затем DBI::execute # $query — это результат функции DBI::prepare
Обратите внимание на условие выборки. В выдачу попадут только опубликованные материалы и только принадлежащие владельцу сайта.