Фотогалерея своими руками с использованием PERL Часть 1
ПРЕДИСЛОВИЕ
В общем-то скриптов фотогалерей, как платных так и бесплатных в сети Интернет довольно достаточно, но всегда все хочется сделать самому, поэтому попробуем определить как нам правильно этос делать, причем что бы это было красиво и легко управлялось. Так как такое понятие как Админ-интерфейс, часто отсутствует, а чаще создано на каком-то минимальном уровне, то особое внимание уделим именно ему. Идею создания подобного скрипта навеяла статья ( http://webscript.ru///www.webscript.ru/stories/02/11/11/9439190 ) опубликованая на webcsript.ru, как практическое примение модулей для работы с графикой.
Какой должна быть собственно фотогалерея? Она должна выводить маленькие иконки фотографий в таблице и постранично, должны быть подписи к фоторгафиям, а сами иконки (а может и подписи тоже) должны быть ссылками на большие фотографии - это внешняя сторона. А что должно быть во внутренней:
- во-первых мы хотим картинки закидывать через upload, а не возится с FTP, а потом возится с ссылками...;
- во вторых иконки для фотографий мы не хотим делать сами: уменьшать изображение в графическом редакторе, потом сопоставлять на сайте полученную иконку с большим изображением, пусть это делает наш скрипт;
- в третьих мы хотим руководить процессом вывода на экран картинок: сколько иконок будет у нас на странице, как они будут располагаться (количество столбцов и строк) и какой будет размер иконки;
- в четвертых мы хотим иметь несколько фотогалерей на одном сайте, и для каждой фотогалереи использовать свой дизайн и свои параметры;
- а в пятых, естественно, мы хотим править подписи к фотографиям, заголовки к фотогалереи, шаблоны и остальные мелочи;
Теперь самое интересное, что для этого нужно:
собственно сервер, на котором мы будем все это обкатывать, с установленным Perl и MySQL (для тех кто не хочет работать с файловыми БД, я лично отношусь к их числу);
к Perl должны быть установленны модули: CGI (для передачи переменных окружениея), DBI и DBD::mysql (для работы с MySQL), Image::Magick (для работы с графикой).
СТРУКТУРА АДМИН ИНТЕРФЕЙСА:
Итак какую структуру данных мы можем обрисовать:
Какие действия будет производить наш админ-интерфейс:
- показ структуры фотогалерей;
- создание, редакитрование, удаление фотогалереи;
- загрузка, изменение, удаление изображения;
- формирование иконок изображений;
ОПИСАНИЕ АДМИН-ИНТЕРФЕЙСА:
Для начала создадим таблице в базе MySQL их всего две:
- таблица фотогалерей со следующими полями gallery_table:
- id - идентификатор галереи (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- name - название, заголовок фотогалереи (тип поля VARCHAR до 250 символов);
- desc - описание фотогалереи (тип поля VARCHAR до 250 символов);
- template - шаблон вывода фотогалереи (тип поля TEXT);
- x_icon - максимальная ширина иконки (тип поля VARCHAR до 5 символов);
- y_icon - максимальная высота иконки (тип поля VARCHAR до 5 символов);
- row_list - количество выводимых строк фотографий (тип поля VARCHAR до 5 символов);
- column_list - количество выводимых колонок фотографий (тип поля VARCHAR до 5 символов);
- таблица фотографий со следующими полями image_table:
- id - идентификатор изображения (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- gallery - id номер фотогалереии к которой относится изображение (тип поля MEDIUMINT);
- name - название изображения, оно же подпись к картинке (тип поля VARCHAR до 250 символов);
- type_image - расширение (тип) изображения (тип поля VARCHAR до 4 символов);
Скрипт создания таблиц:
#!/usr/bin/perl
use DBI;
$name_base_mysql = "mybase"; # база данных MySQL
$host_base_mysql = "localhost"; # host MySQL
$port_base_mysql = "3306"; # порт MySQL
$user_base_mysql = "user"; # пользователь MySQL
$pass_base_mysql = "qwerty"; # пароль пользователя MySQL
$dbh = "DBI:mysql:$name_base_mysql:$host_base_mysql:$port_base_mysql";
$dbh = DBI->connect($dbh, $user_base_mysql, $pass_base_mysql);
$dbh -> do("CREATE TABLE IF NOT EXISTS image_table (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
gallery MEDIUMINT NOT NULL,
name VARCHAR(250) NOT NULL,
type_image VARCHAR(50) NOT NULL,
PRIMARY KEY (id),
INDEX (gallery))");
$dbh -> do("CREATE TABLE IF NOT EXISTS gallery_table (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name VARCHAR(250) NOT NULL,
titling VARCHAR(250) NOT NULL,
template TEXT NOT NULL,
x_icon VARCHAR(5) NOT NULL,
y_icon VARCHAR(5) NOT NULL,
row_list VARCHAR(5) NOT NULL,
column_list VARCHAR(5) NOT NULL,
PRIMARY KEY (id))");
print "Content-type: text/html; charset=windows-1251\n\n";
print qq "Create table OK!";
exit;
Здесь в принципе ничего сложного нет, только единственное иногда некоторые администраторы не дают привилегии для создания и удаления таблиц, поэтому если не работает, бегом к администратору...
Теперь перейдем непостредственно к нашему скрипту админ-интерфейса. Для этого нам понадобится четыре шаблона:
шаблон загрузки изображения (upload.htm):
<html>
<head>
<meta http2-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Загрузка фoтoграфии</title>
</head>
<body>
<table width="98%" border="0" align="center" cellpadding="4" cellspacing="1">
<tr>
<td bgcolor="#B0B0B0" colspan="2">
<font color="#f5f5f5"><b>Загрузка фотографии</b></font>
</td>
</tr>
<form name="form1" method="post" action="%script_url%" enctype="multipart/form-data">
<tr>
<td width="200" valign="top">Название фотографии:</td>
<td align="left">
<input class="input" name="fdb0" type="text" size="40" maxlength="250" value="">
</td>
</tr>
<tr>
<td width="200" valign="top">Галерея фотографии:</td>
<td align="left">
<select name="fdb1">
<!-- 1 --> <option value="%id_category%" %selected%> %name_category%</option>
<!-- 1_insert -->
</select>
</td>
</tr>
<tr>
<td width="200" valign="top">Путь к файлу:</td>
<td align="left">
<input class="input" name="image" type="file" size="250">
</td>
</tr>
<tr>
<td bgcolor="#F5F5F5" width="200" valign="top"></td>
<td bgcolor="#F5F5F5" height="30" align="left">
<input type="hidden" name="mod" size="40" maxlength="256" value="%mod%">
<input type="hidden" name="edit" size="40" maxlength="256" value="%edit%">
<input type="hidden" name="doing" size="40" maxlength="256" value="afform">
<input class="input" type="submit" name="Submit" value="Загрузить">
<input class="input" type="reset" value="Очистить">
</td>
</tr>
</form>
</table>
</body>
</html>
шаблон редактирования (он же удаления) изображения (edit.htm):
<html>
<head>
<meta http2-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Форма редактирования (удаления) изображения</title>
</head>
<body>
<table width="98%" border="0" align="center" cellpadding="4" cellspacing="1">
<tr>
<td bgcolor="#B0B0B0" colspan="2">
<font color="#f5f5f5"><b>%doing% изображения</b></font>
</td>
</tr>
<form name="form1" method="post" action="%script_url%" enctype="text/html">
<tr>
<td width="200" valign="top">Название изображения:</td>
<td align="left">
<input class="input" name="fdb0" type="text" size="40" maxlength="250" value="%name%">
</td>
</tr>
<tr>
<td width="200" valign="top">Галерея изображения:</td>
<td align="left">
<select name="fdb1">
<!-- 1 --> <option value="%id_category%" %selected%> %name_category%</option>
<!-- 1_insert -->
</select>
</td>
</tr>
<tr>
<td width="200" valign="top"></td>
<td align="left">
<a href="%link_image%" target="_blank"><img src="%link_icon%" border="0" align="middle" vspace="2" hspace="2"></a>
</td>
</tr>
<tr>
<td bgcolor="#F5F5F5" width="200" valign="top"></td>
<td bgcolor="#F5F5F5" height="30" align="left">
<input type="hidden" name="mod" size="40" maxlength="256" value="%mod%">
<input type="hidden" name="edit" size="40" maxlength="256" value="%edit%">
<input type="hidden" name="id" size="40" maxlength="256" value="%id%">
<input type="hidden" name="doing" size="40" maxlength="256" value="afform">
<input class="input" type="submit" name="Submit" value="%doing%">
<input class="input" type="reset" value="Очистить">
</td>
</tr>
</form>
</table>
</body>
</html>
шаблон редактирования (он же создания и удаления) галереи (gallery.htm):
<html>
<head>
<meta http2-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Форма добавления, редактирования и удаления фотогалереи</title>
</head>
<body>
<table width="98%" border="0" align="center" cellpadding="4" cellspacing="1">
<tr>
<td bgcolor="#B0B0B0" colspan="2">
<font color="#f5f5f5"><b>%doing% галереи</b></font>
</td>
</tr>
<form name="form1" method="post" action="%script_url%" enctype="text/html">
<tr>
<td width="200" valign="top">Название галереи:</td>
<td align="left">
<input class="input" name="fdb0" type="text" size="40" maxlength="250" value="%name%">
</td>
</tr>
<tr>
<td width="200" valign="top">Описание галереи:</td>
<td align="left">
<input class="input" name="fdb1" type="text" size="40" maxlength="250" value="%titling%">
</td>
</tr>
<tr>
<td width="200" valign="top">Количество строк:</td>
<td align="left">
<input class="input" name="fdb2" type="text" size="5" maxlength="5" value="%row%">
</td>
</tr>
<tr>
<td width="200" valign="top">Количество колонок:</td>
<td align="left">
<input class="input" name="fdb3" type="text" size="5" maxlength="5" value="%column%">
</td>
</tr>
<tr>
<td width="200" valign="top">Высота иконки:</td>
<td align="left">
<input class="input" name="fdb4" type="text" size="5" maxlength="5" value="%y_icon%"> (px)
</td>
</tr>
<tr>
<td width="200" valign="top">Ширина иконки:</td>
<td align="left">
<input class="input" name="fdb5" type="text" size="5" maxlength="5" value="%x_icon%"> (px)
</td>
</tr>
<tr>
<td width="200" valign="top">Шаблон вывода галереи:</td>
<td align="left">
<table width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
<tr>
<td>
<textarea name="fdb6" cols="70" rows="20">%html%</textarea>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#F5F5F5" width="200" valign="top"></td>
<td bgcolor="#F5F5F5" height="30" align="left">
<input type="hidden" name="mod" size="40" maxlength="256" value="%mod%">
<input type="hidden" name="edit" size="40" maxlength="256" value="%edit%">
<input type="hidden" name="id" size="40" maxlength="256" value="%id%">
<input type="hidden" name="doing" size="40" maxlength="256" value="afform">
<input class="input" type="submit" name="Submit" value="%doing%">
<input class="input" type="reset" value="Очистить">
</td>
</tr>
</form>
</table>
</body>
</html>
шаблон вывода списка фотографий (show.htm):
<html>
<head>
<meta http2-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Список изображений</title>
</head>
<body>
<table width="98%" border="0" align="center" cellpadding="4" cellspacing="1">
<tr>
<td bgcolor="#B0B0B0" colspan="2">
<font color="#f5f5f5"><b>Список фотогалерей</b></font>
</td>
</tr>
<tr>
<td width="50"></td>
<td align="left">
<table width="60%" border="0" align="left" cellpadding="0" cellspacing="0" summary="">
<tr>
<form action="%script_url%" method="get">
<td>
<input type="hidden" name="mod" value="category" enctype="text/html">
<input type="hidden" name="edit" value="new">
<input type="submit" value="Новая фотогалерея">
</td>
</form>
<form action="%script_url%" method="get">
<td>
<input type="hidden" name="mod" value="image" enctype="text/html">
<input type="hidden" name="edit" value="upload">
<input type="hidden" name="cat" value="%edit%">
<input type="submit" value="Загрузить изображение">
</td>
</form>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#B0B0B0" colspan="2">
<font color="#f5f5f5"><b>Список фотографий</b></font>
</td>
</tr>
<tr>
<td align="left" colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<!-- 1 --><table width="100%" border="0" cellspacing="0" cellpadding="0">
<!-- 1 --> <form action="%script_url%" method="get">
<!-- 1 --> <tr bgcolor="#B0C4DE">
<!-- 1 --> <td width="300" valign="middle">
<!-- 1 --> <b> [ %name_category% </b>
<!-- 1 --> <a href="%script_url%?edit=%id%">Раскрыть</a>
<!-- 1 --> </td>
<!-- 1 --> <td width="230" valign="middle">
<!-- 1 --> <input name="mod" type="hidden" value="category">
<!-- 1 --> <input name="edit" type="hidden" value="edit">
<!-- 1 --> <input name="id" type="hidden" value="%id%">
<!-- 1 --> <input class="input" name="" type="submit" value="Редактировать">
<!-- 1 --> </td>
<!-- 1 --> </form>
<!-- 1 --> <form action="%script_url%" method="get">
<!-- 1 --> <td valign="middle">
<!-- 1 --> <input name="mod" type="hidden" value="category">
<!-- 1 --> <input name="edit" type="hidden" value="delete">
<!-- 1 --> <input name="id" type="hidden" value="%id%">
<!-- 1 --> <input class="input" name="" type="submit" value="Удалить">
<!-- 1 --> </td>
<!-- 1 --> </tr>
<!-- 1 --> </form>
<!-- 1 --></table>
<!-- 2 --><table width="100%" border="0" cellspacing="0" cellpadding="0">
<!-- 2 --> <form action="%script_url%" method="get">
<!-- 2 --> <tr>
<!-- 2 --> <td width="300"> [ %name_image% ] </td>
<!-- 2 --> <td width="120">
<!-- 2 --> <input name="mod" type="hidden" value="image">
<!-- 2 --> <input name="edit" type="hidden" value="edit">
<!-- 2 --> <input name="id" type="hidden" value="%id%">
<!-- 2 --> <input class="input" name="" type="submit" value="Редактировать">
<!-- 2 --> </td>
<!-- 2 --> </form>
<!-- 2 --> <form action="%script_url%" method="get">
<!-- 2 --> <td align="left" width="70">
<!-- 2 --> <input name="mod" type="hidden" value="image">
<!-- 2 --> <input name="edit" type="hidden" value="delete">
<!-- 2 --> <input name="id" type="hidden" value="%id%">
<!-- 2 --> <input class="input" name="" type="submit" value="Удалить">
<!-- 2 --> </td>
<!-- 2 --> <td align="center">
<!-- 2 --> <a href="%link_image%" target="_blank">
<!-- 2 --> <img src="%link_icon%" border="0" align="middle" vspace="2" hspace="2"></a>
<!-- 2 --> </td>
<!-- 2 --> </tr>
<!-- 2 --> </form>
<!-- 2 --> <tr><td colspan="4"><hr size="1" color="#F5F5F5"></td></tr>
<!-- 2 --></table>
<!-- 1_insert -->
</td>
</tr>
</table>
</body>
</html>
Теперь обсудим какие что же у нас жа шаблоны получились. Первые три обычные формы без особых сложностей, единственно параметр формы загрузки изображения enctype="multipart/form-data" так как мы должны передать не текст, а файл. Так же в первых двух шаблонах есть динамические внедрения (<!-- 1 --> и <!-- 1_insert -->), так как мы должны будем первоначально формировать список наших галерей для последующего их выбора. Вот с четвертым шаблоном нужно повозится. Во-первых мы должны сформировать и выдать список фотогалерей (<!-- 1 --> - одна строка списка), во-вторых сформировать и выдать список фотографий выбранной фотогалереи (<!-- 2 --> - одна строка списка).
Переменные и параметры которые мы бодем обрабатывать скриптом я, для удобства, выделил темно-желтым цветом. Выделим их в список и определим, что мы с ними предполагаем делать:
- mod - параметр указывающий объект с которым мы непосредственно работаем: фотогалерея (category) или изображение (image). Значение подставляется скриптом вместо выражения %mod%;
- edit - параметр указывающий производимое действие над объектом: загрузка (upload), создание (new), изменение (edit), удаление (delete). Значение подставляется скриптом вместо выражения %edit%. При работе со списком указывает фотогалерею (идентификатор), которую просматриваем. Значение подставляется скриптом вместо выражения %id%;
- id - индентификатор объекта. Значение подставляется скриптом вместо выражения %id%;
- fdb[0-6] - параметры передаваемые из формы и указывающиеся непосредственно пользователем. Значение подставляется скриптом вместо выражений: %name%, %titling%, %row%, %column%, %y_icon%, %x_icon%, %html%, %id_category%, берущихся из нашей базы данных;
- image - фотография которую мы хотим загрузить;
- doing - подтверждение операции над объектом;
- %script_url% - URL нашего скрипта. Можно конечно указывать его и сразу, но при переносе скрипта на другой хост прийдется переправлять все шаблоны, что несколько неудобно;
- остальные параметры заключенные %, проще будет объяснить в процессе кода.
Теперь можно заняться непосредственно скриптом. Начало стандартное:
#!/usr/bin/perl
use CGI;
use DBI;
use Image::Magick;
use strict;
Так же я рекомендовал ввести еще дополнительные параметры работы скрипта:
use CGI::Carp qw (fatalsToBrowser); # что бы ошибки скрипта выпадали в браузер
$CGI::POST_MAX = 262144; # что бы не было желания закачивать картинки в особо крупных размерах :-)
Устанавливаем начальные переменные:
use vars '$path_image', '$name_base_mysql', '$host_base_mysql', '$port_base_mysql', '$user_base_mysql', '$pass_base_mysql',
'$mod', '$edit', '$id', '$doing', '$cat', '$image', '@fdb', '@temp', '$dbh', '$sth', '$sql', '$tmp', '$image_url';
$path_image = "/home/site/mysite/html/gallery/"; # путь где будут располагаться фотографии
$script_url = "//www.mysite.ru/cgi-bin/gallery/gallery.pl"; # url где располагается наш скрипт
$image_url = "//www.mysite.ru/gallery/"; # url где располагаются наши фотографии
$name_base_mysql = "mybase"; # база данных MySQL
$host_base_mysql = "localhost"; # host MySQL
$port_base_mysql = "3306"; # порт MySQL
$user_base_mysql = "user"; # пользователь MySQL*
$pass_base_mysql = "qwerty"; # пароль пользователя MySQL
*Привилегии для пользователя MySQL можно установить только SELECT, INSERT, UPDATE, DELETE
Забираем "переменные окружения":
my ($query);
$query = new CGI;
$mod = $query -> param('mod');
$edit = $query -> param('edit');
$id = $query -> param('id');
$doing = $query -> param('doing');
$cat = $query -> param('cat');
$image = $query -> param('image');
$fdb[0] = $query -> param('fdb0');
$fdb[1] = $query -> param('fdb1');
$fdb[2] = $query -> param('fdb2');
$fdb[3] = $query -> param('fdb3');
$fdb[4] = $query -> param('fdb4');
$fdb[5] = $query -> param('fdb5');
$fdb[6] = $query -> param('fdb6');
Перенаправляем на процедуру в соответствии с переданными переменными $mod и $edit:
if ($mod eq 'category') {
if ($edit eq 'new') {&mod_category_new}
if ($edit eq 'edit') {&mod_category_edit}
if ($edit eq 'delete') {&mod_category_delete}
}
if ($mod eq 'image') {
if ($edit eq 'upload') {&mod_image_upload}
if ($edit eq 'edit') {&mod_image_edit}
if ($edit eq 'delete') {&mod_image_delete}
}
&mod_list_gallery;
exit;
В итоге получается, что скрипт вызывает определенную процедуру в соответствии с двумя переданными параметрами $mod и $edit - объект и производимые действия над объектом. Если же нас не удовлетворяет хоть один из параметров, то выходим в процедуру просмотра фотогалерей.
Часть 2 >>>
|