3 мая 2002 г.
Сегодня я попытаюсь рассказать вам о том, как написать гостевую книгу на PHP и MySQL. Ничего сложного в этом нет, да и возможности данной гостевой не очень большие: постраничный вывод записей, возможность удалять записи.
Допустим, что у вас уже есть PHP, MySQL и веб-сервер. Вы все установили и настроили.
Начнем с создания таблицы, в которой будут храниться данные нашей гостевой книги. Будем спрашивать у пользователя имя и комментарий. При желании пользователь сможет сообщить адреса электронной почты и домашней странички. Для администрирования книги нам понадобится еще одно поле, уникальное для каждой записи, идентификатор. Ну и дата, конечно. В итоге получается такая таблица:
CREATE TABLE gb (
id int(10) unsigned NOT NULL auto_increment,
datetime datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
name varchar(100) NOT NULL,
email varchar(100),
www varchar(100),
message text NOT NULL,
PRIMARY KEY (id)
);
Таблица у нас есть. Теперь можно приступать к программированию.
Для начала определим константы, которые понадобятся нам в дальнейшем:
<?
/*
* defines.php -- константы
*/
// общие константы
define('PATH', '/gb/'); // путь к гостевой книге
define('RECSPERPAGE', 10); // количество записей на одной странице
// Параметры БД
define('DBHOST', 'localhost'); // имя хоста
define('DBUSER', 'root'); // имя пользователя
define('DBPASSWD', 'root'); // пароль
define('DBNAME', 'test'); // имя базы данных
?>
Напишем модуль для работы с СУБД MySQL. Я вынес все функции работающие с MySQL в отдельный модуль, чтобы их можно было легко переписать при смене СУБД. Думаю, комментариев в исходнике будет достаточно.
<?
/*
* bd.php -- работа с MySQL
*/
// подключение к СУБД и открытие базы данных
function db_connect($host, $user, $passwd, $dbname)
{
$link = @mysql_connect($host, $user, $passwd) or die('Не могу подключиться к серверу баз данных');
@mysql_select_db($dbname) or die('Не могу открыть базу данных «'.$dbname.'»');
return $link;
}
// запрос к БД
function db_query($query)
{
$result = @mysql_query($query) or die('Не могу сделать запрос к базе данных');
return $result;
}
// получение текущей записи результата в виде массива
function db_fetch_array($result)
{
return mysql_fetch_array($result);
}
// уничтожение результата
function db_free_result($result)
{
return mysql_free_result($result);
}
// получение числа записей (строк) в результате
function db_num_rows($result)
{
return mysql_num_rows($result);
}
?>
Для написания нормальной гостевой книги нам понадобятся еще две библиотеки. Первая работа со строками:
<?
/*
* strings.php -- функции для работы со строками
*/
//проверяет является ли строка адресом e-mail
function strings_isemail($string)
{
return ereg(
'^([a-zA-Z0-9_]|-|.)+'.
'@'.
'([a-zA-Z0-9_]|-|.)+'.
'[a-zA-Z]{2,4}$',
$string);
}
//добавление ссылок на http2 и e-mail
function strings_addlinks($string)
{
$string = ereg_replace("(//[a-zA-Z0-9_.#%?/&=-]*)", "<a href="1">1</a>", $string);
$string = ereg_replace("(([a-zA-Z0-9_]|-|.)+@([a-zA-Z0-9_]|-|.)+[a-zA-Z]{2,4})", "<a href="mailto:1">1</a>", $string);
return $string;
}
// чистка строки
function strings_clear($string)
{
$string = stripslashes($string); //восстановление кавычек после формы
$string = htmlspecialchars($string); //замена специальных символов их кодами
$string = str_replace("'", "'", $string); //замена апострофа его кодом (нужно для того, чтобы нормально работали запросы)
$string = trim($string); //снос ведущих пробелов
return $string;
}
// кастрирование строки
function strings_stripstring($text, $wrap, $length)
{
// разбиваем очень длинные слова (длиннее $wrap) на несколько маленьких
$wordlen = 0;
for($i = 0; $i < strlen($text); $i++)
{
$text2 .= $text[$i];
if($text[$i] != " ")
$wordlen++;
else
$wordlen = 0;
if($wordlen > $wrap)
{
$text2 .= " ";
$wordlen = 0;
}
}
$text = $text2;
// обрезаем строку до нужной длинны ($length)
$text = substr($text, 0, $length);
return $text;
}
// замена символов перевода строки и возвата каретки на <br>
function strings_addbreaks($string)
{
return str_replace("rn", "<br>", $string);
}
?>
Написание же второго модуля аутентификации администратора я оставляю вам в качестве домашнего задания. Есть достаточно много способов и их обсуждение тема отдельной статьи. Я приведу лишь функцию-заглушку:
<?
/*
* auth.php -- аутентификация пользователей
*/
/*
* ВНИМАНИЕ! Ни в коем случае не используйте этот файл в реальных проектах.
* Сделайте проверку пароля или что-то в этом духе, иначе вашу гостевую просто
* сломают.
*/
// проверка: администратор или обычный пользователь
function auth_is_admin()
{
global $HTTP_GET_VARS;
return $HTTP_GET_VARS['admin'];
}
?>
Далее идет достаточно большой модуль, в котором содержится почти весь HTML код гостевой книги, шаблон. В нем нет ничего сложного и его написание можно свалить на верстальщика, если у вас таковой имеется.
<?
/*
* template.php -- шаблон
*/
// заголовок страницы
function template_header($page)
{
print '<html>
<head>
<title>page '.$page.' < madman/gb</title>
<style>
body{
padding: 15px;
margin: 0;
color: #333;
background-color: #eee;
border-left: 30px solid #adba8e;
font: 500 .9em verdana, arial, helvetica;
}
a:link{color: #250;}
a:visited{color: #639;}
a:active,a:hover{
color: #c00;
text-decoration: underline;
}
.c{margin-bottom: 10px;}
.cn{
background-color: #d2d6bc;
padding: 2px 4px;
margin-bottom: 4px;
}
h2{font: 700 20pt/24pt verdana, arial, helvetica;}
</style>
</head>
<body>
<h2>Гостевая книга Васи Пупкина</h2>';
}
// окончание страницы
function template_footer()
{
print '<p>Guestbook by Artem Sapegin v 1.0; [c] zooz</p></body></html>';
}
// форма добавления новой записи
function template_form($name, $email, $www, $message, $error)
{
// вывод сообщения об ошибке
function error($error)
{
if($error) print '<br><font color=#880000>'.$error.'</font>';
}
print '<h2>Добавить новое сообщение</h2>
<p><table cellspacing="2" cellpadding="2" border="0"><form action='.PATH.'?add=1 method=post><tr>
<td>Имя:</td>
<td><input type=text name="name" size=30 maxlength=100 value="'.$name.'">';
error($error['name']);
print '</td>
</tr><tr>
<td>Email:</td>
<td><input type=text name="email" size=30 maxlength=100 value="'.$email.'">';
error($error['email']);
print '</td>
</tr><tr>
<td>URL:</td>
<td><input type=text name="www" size=30 maxlength=100 value="'.$www.'">';
print '</td>
</tr><tr>
<td>Сообщение:</td>
<td><textarea cols=40 rows=5 name="message">'.$message.'</textarea>';
error($error['message']);
print '</td>
</tr><tr>
<td> </td>
<td><input type=submit value="Добавить сообщение"></td>
</form></tr>
</table>';
}
// печать одной записи гостевой книги
function template_show_body($id, $name, $email, $www, $message, $datetime)
{
$out = '<div class=c><div class=cn><b>'.$name.'</b> ';
// если есть email или homepage -- печатаем их
if($email || $www)
{
$out .= '( ';
if($email)
$out .= ' <a href=mailto:'.$email.'>email</a>';
if($email && $www)
$out .= ' | ';
if($www)
$out .= ' <a href='.$www.'>www</a>';
$out .= ' )';
}
$out .= ' пишет '.$datetime.':</div>'.$message.'</div>';
// если гостевую книгу просматривает администратор -- печатаем кнопку удаления записи
if(auth_is_admin())
{
$out .= '<div class=c>[ <a href='.PATH.'?del='.$id.'>удалить</a> ]</div>';
}
return $out;
}
?>
И вот, мы наконец-то дошли до главного. До модуля гостевой книги. Постараюсь написать побольше комментариев, чтобы вам было понятно.
<?
/*
* gb.php -- гостевая книга
*/
// добавление записи в гостевую книгу
function gb_add($name, $email, $www, $message, &$error)
{
// проверка на правильность заполнения полей
$error = '';
if(!$name)
$error['name'] = 'Это поле обязательное';
if(!$message)
$error['message'] = 'Это поле обязательное';
if($email && !strings_isemail($email))
$error['email'] = 'Неверный адрес email';
// если не было ошибок -- добавляем
if(!$error)
{
// чистим данные. эти функции находятся в модуле strings.php
$name = strings_clear($name);
$message = strings_clear($message);
$name = strings_stripstring($name, 15, 100);
$email = strings_stripstring($email, 100, 100);
$www = strings_stripstring($www, 100, 100);
$message = strings_stripstring($message, 40, 2000);
$message = strings_addlinks($message);
$message = strings_addbreaks($message);
// если пользователь поленился написать // перед адресом -- сделаем это за него
if($www)
if(!ereg("^//(.*)$", $www)) $www = '//'.$www;
// запрос на добавление записи в базу данных
db_query("INSERT INTO gb (name, email, www, message, datetime) VALUES('".$name."', '".$email."', '".$www."', '".$message."', NOW())");
// перекидываем браузер на первую страницу
// это нужно, чтобы, если пользователь нажмет кнопку Refresh, запись не добавилась еще раз
header('Location: '.PATH."?page=1nn"); // ???
}
}
// удаление записи из гостевой книги
function gb_delete($id)
{
// запрос на удаление записи из базы данных
// WHERE id = '.$id указывает на запись, которую следует удалить
db_query('DELETE FROM gb WHERE id = '.$id);
header('Location: '.PATH."?page=1nn"); // ???
}
// вывод страницы с записями
function gb_show($page)
{
// положение первой записи страницы
$begin = ($page 1) * 10;
// выборка записей из базы данных
// SELECT * FROM gb -- все поля из бд gb
// ORDER BY datetime DESC -- сортировка по дате, новые сверху
// LIMIT '.$begin.','.RECSPERPAGE -- ограничение: RECSPERPAGE (см. defines.php) записей начиная с $begin
$result = db_query('SELECT * FROM gb ORDER BY datetime DESC LIMIT '.$begin.','.RECSPERPAGE);
// цикл по всем выбранным записям
while($row = db_fetch_array($result))
{
$out .= template_show_body($row['id'], $row['name'], $row['email'], $row['www'], $row['message'], $row['datetime']);
}
// уничтожаем результат
db_free_result($result);
print $out;
}
// вывод списка страниц
function gb_showpages($current)
{
// узнаем число записей в гостевой книге
// ceil() -- округление вверх
$result = db_query('SELECT * FROM gb');
$pages = ceil(db_num_rows($result) / RECSPERPAGE);
// печатаем ссылки на страницы (номер текущей страницы не является ссылкой)
print '<div class=c>';
for($i = 1; $i <= $pages; $i++)
{
if($i != $current)
print ' | <a href='.PATH.'?page='.$i.'>'.$i.'</a>';
else
print ' | '.$i;
}
print ' |';
// если это не полследняя страница печатаем ссылку "Дальше"
if($current < $pages)
print ' <a href='.PATH.'?page='.($current + 1).'>Дальше >></a>';
print '</div>';
}
?>
Остался последний штрих объединить все это вместе. Игра в виртуальные игровые автоматы – это просто, доступно и удобно, ведь заниматься этим можно в любое время и в любом месте. Тут уж совсем все просто:
<?
/*
* Guestbook by Artem Sapegin v 1.0; ©2002
* vampire@au.ru | //madman.km.ru/
*/
/*
* index.php -- главный файл
*/
// подключаем модули
require('my/defines.php');
require('my/template.php');
require('engine/lib/strings.php');
require('engine/lib/auth.php');
require('engine/lib/bd.php');
require('engine/gb.php');
// подключаемся к СУБД
db_connect(DBHOST, DBUSER, DBPASSWD, DBNAME);
$name = $HTTP_POST_VARS['name'];
$email = $HTTP_POST_VARS['email'];
$www = $HTTP_POST_VARS['www'];
$message = $HTTP_POST_VARS['message'];
// если в GET-запросе не указан номер страницы, выводим первую
if(!isset($HTTP_GET_VARS['page']))
$page = 1;
else
$page = $HTTP_GET_VARS['page'];
// если нужно добавить запись, добавляем
if($HTTP_GET_VARS['add'])
gb_add($name, $email, $www, $message, $formerr);
// если нужно удалить запись, удаляем
if(isset($HTTP_GET_VARS['del']))
gb_delete($HTTP_GET_VARS['del']);
// печатаем гостевую книгу
template_header($page);
gb_showpages($page);
gb_show($page);
gb_showpages($page);
template_form($name, $email, $www, $message, $formerr);
template_footer();
?>
Как видите, ничего сложного не было. Но если вопросы все же возникнут, постараюсь помочь.