php2 Задачи ГК • • • Сохранять добавленное сообщение. Производить проверку добавляемого сообщения перед сохранением. Выводить все сообщения на экран. Модули • • • config.php - здесь будут храниться общие настройки гостевой книги. base.txt - файл, где будут храниться все сообщения, наша своеобразная база данных. guest.php - здесь будет содержаться непосредственно наш скрипт. guest.php • • • • <HTML> <HEAD> <TITLE>Гостевая книга</TITLE> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> • </HEAD> • <BODY> • <? require("config.php"); • • • • • • • • • • • • • • • • • function show_form() { ?> <form method="post" action=""> Имя<br> <input type="text" name="name" maxlength="22"> <br> E-mail<br> <input type="text" name="email" maxlength="21"> <br> Сообщение<br> <textarea cols="70" rows="20" name="mess"></textarea><br> <input type="submit" value="Послать"> <input type="reset" value="Очистить"> </form> <? } config.php • <? $base = "base.txt"; guest.php • function save_mess() • { • global $name, $email, $mess, $base; • • • • • • $date = date("d.m.y - H:i:s"); $text = $name."^^".$email."^^".$date."^^".$mess."\n"; $fp = fopen($base,"a"); fputs($fp, $text); fclose($fp); } config.php • $MessOnScreen = 10; • Ограничение по кол-ву сообщений guest.php • function show_mess() • { • global $base, $MessOnScreen; • • • • • • • • • • • • $file = file($base); $file = array_reverse($file); echo "<table>"; if(sizeof($file) < $MessOnScreen) $MessOnScreen = sizeof($file); for ($i = 0; $i < $MessOnScreen; $i++) { $mess = explode("^^",$file[$i]); ?> • <tr> • <td> • <p>Написал: • <? echo "<a href='mailto:".$mess[1]."'>".$mess[0]."</a>"; • echo "<br>"; • echo $mess[2]; ?> • </td> • <td> • <p><?=$mess[3];?></td> • </tr> • <? • } • echo "</table></td>"; • } • Функцией file() получаем массив, где в каждом элементе содержится строка с одним "блоком" - именем писавшего, адресом и сообщением. • Изменяем порядок элементов на обратный, так что самая последняя запись становится у нас первым элементом массива. • Сравниваем количество элементов в $file (количество сообщений) с указанным в $MessOnScreen лимитом, и если оно меньше этого значения, то $MessOnScreen устанавливаем в число элементов $file. • выполняется цикл вывода сообщений. С каждым проходом цикла значение переменной цикла увеличивается на единицу. Таким образом самые свежие сообщения (те, что были приписаны позже всех и находятся внизу файлабазы) выведутся первыми, а более старые - последними. • переменной $mess присваиваем массив с элементами: 0-ой элемент - имя 1-ый элемент - адрес электронной почты 2-ой элемент - время добавления сообщения 3-й элемент - само сообщение вывод • запись <?=$mess[2];?> • эквивалентна <? echo $mess[2];?> • function check_mess() • { • global $name, $email, $mess; • • • $mess=trim($mess); $email=trim($email); $name=trim($name); • • • • • $name = htmlspecialchars($name); $email = htmlspecialchars($email); $mess = htmlspecialchars($mess); $mess = str_replace("\n","<br>",$mess); • trim() отрезает все пустые символы (пробелы, переводы строк, символы табуляции) в начале и в конце строк. • str_replace заменяет с помощью функции все символы перевода строки на тег <br>. • htmlspecialchars() обрабатывает все специальные символы HTML, то есть символ < переходит в &lt; и так далее • function output_err($num) • { • global $err; • ?> • <center><h1>Oшибка!</h1></center> • <p><?=$err[$num];?> • • <? • exit(); • } • В файле config.php в массиве $err будут перечислены сообщения для вывода при соответствующей ошибке. Обратите внимание, что мы при помощи функции exit() прекращается работа скрипта после вывода сообщения об ошибке • if (empty($name)) output_err(2); • if (!preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[az]{2,3}/i", $email)) • { • output_err(1); • } • • if (preg_match("/[^(\w)|(\x7F\xFF)|(\s)]/",$name)) output_err(2); • } • проверить, чтобы e-mail был вида [email protected], • проверить имя: оно должно содержать только буквы латинского и русского алфавита и знак подчеркивания (_). • при несоблюдении этих условий задействуется функция output_err() с аргументом, представляющим собой индекс массива $err для соответствующей ошибки. config.php • $err[1] = "Неверно введен e-mail"; $err[2] = "Неверно введено имя"; guest.php • function check_for_length() • { • global $mess, $email, $name, $MessLength; • if (strlen($mess)>$MessLength) output_err(3); • $email=substr($email, 0, 21); • $name=substr($name, 0, 22); • } • сверяется длина сообщения с указанной в переменной $MessLength с помощью функции strlen(), которая возвращает количество символов в строке • используется функцию output_err() в случае превышения длины сообщения над лимитом config.php • $MessLength = 1000; $err[3] = "Недопустимая длина сообщения"; guest.php • function check_mess_for_flud() • { • global $mess,$base; • • • • • • } $file=file($base); $file=implode("",$file); $mess=preg_quote($mess); if (eregi($mess, $file)) output_err(4); $mess = stripslashes($mess); • получается массив строк файла-базы с помощью функции file() • массив объединяется в одну переменную • "квотируется" сообщение пользователя • смотрим, встречается ли этот текст в базе или нет • если встречался, выводится ошибку • возвращается текст в переменной $mess в первоначальное состояние, то есть убирает все обратные слеши \ перед специльными символами, которые были добавлены функцией preg_quote config.php • $err[4] = "Такое сообщение уже существует"; guest.php • function del_mess_from_file() • { • global $base, $MessInFile; • • • • • • • • • • • $file = file($base); $k = 0; if($MessInFile<sizeof($file)) { for($i=sizeof($file)-$MessInFile; $i<sizeof($file); $i++) { $ResFile[$k]=$file[$i]; $k++; } • $fp=fopen($base,"w"); • for($i=0; $i<sizeof($ResFile); $i++) • { • fputs($fp, $ResFile[$i]); • } • fclose($fp); • } • } config.php • $MessInFile = 20; • function check_mess() • { • global $name, $email, $mess; • • • $mess=trim($mess); $email=trim($email); $name=trim($name); • • • • • • • $name=htmlspecialchars($name); $email=htmlspecialchars($email); $mess=htmlspecialchars($mess); $mess = str_replace("\n","<br>",$mess); • check_for_length(); //добавили • • if (empty($name)) output_err(2); if (!preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[az]{2,3}/i", $email))output_err(1); • if (preg_match("/[^(\w)|(\x7F-\xFF)|(\s)]/",$name)) output_err(2); • check_mess_for_flud(); //добавили • del_mess_from_file(); //добавили • } • if ($mess) { check_mess(); save_mess(); } show_mess(); show_form(); ?> </BODY> </HTML> • В PHP предусмотрено два способа передачи ID сессии (сокращенно SID): • Через метод GET. Тогда посетитель будет видеть в своем броузере адресную строку следующего типа: http://server.com/main.php?PHPSESSID=bdd95 bcd4e1e2ef5ec57fc83a69bba86 • Через Cookie. Здесь, соответственно, посетитель не будет видеть признаков существования сессии, SID передается через Cookie. • Любая сессия открывается с помощью функции session_start(), создающей специальный служебный файл с именем, соответствующим ID сессии, в который впоследствии будут записаны все данные, связанные с текущей сессией. Место размещения этих файлов зависит от настроек PHP. Так что если вы используете в своих скриптах сессии, не забывайте иногда подчищать директорию с этими временными файлами, так как там со временем может накопиться солидное количество ненужных файлов. • запись данных в сессию функция session_register(). Она сохраняет в файл текущей сессии значения указанных переменных • session_start(); session_register('name', 'birth'); $name = "Вася Пупкин"; $birth = "4 марта"; • Обратной функции session_register() является функция session_unregister(), которая удаляет данные из текущей сессии. Эта функция используется довольно редко, но иногда бывает очень полезной. Например, в том случае, если вы регистрируете в сессию большое количество переменных, чтобы не перезагружать файл текущей сессии, можно удалить оттуда уже ненужные значения. Дополнительные функции работы с сессиями • session_id • session_name • session_destroy • session_start(); echo session_name(); session_name("MySession"); echo session_name(); Механизм отправки HTTP заголовков в PHP • header("HTTP заголовок", необязательный параметр replace); • должна быть вызвана в самом начале документа • Опциональный параметр replace может принимать значения типа bool (true или false) и указывает на то, должен ли быть замещен предыдущий заголовок подобного типа, либо добавить данный заголовок к уже существующему • Опциональный параметр replace может принимать значения типа bool (true или false) и указывает на то, должен ли быть замещен предыдущий заголовок подобного типа, либо добавить данный заголовок к уже существующему. • функция headers_sent(), которая в качестве результата возвращает true в случае успешной отправки заголовка и false в обратном случае. Cache-control. • "Cache-control: " значение • Заголовок управления кешированием страниц. Вообще, данная функция является одной из самых распространенных в использовании заголовков. • no-cashe - Запрет кеширования. Используется в часто обновляемых страницах и страницах с динамическим содержанием. Его дейсвтие подобно META тегу "Pragma: nocache". • public - Разрешение кеширования страницы как локальным клиентом, так и прокси-сервером. • private - Разрешение кеширования только локальным клиентом. • max-age - Разрешение использования кешированного документа в течение заданного времени в секундах. • header("Cache-control: private, max-age = 3600") /* Кеширование локальными клиентами и использование в течение 1 часа */ Expires • "Expires: " HTTP-date • Устанавливает дату и время, после которого документ считается устаревшим. Дата должна указываться в следующем формате (на английском языке): • День недели (сокр.) число (2 цифры) Месяц (сокр.) год часы:минуты:секунды GMT • Fri, 09 Jan 2002 12:00:00 GMT • Текущее время в этом формате возвращает функция gmdate() в следующем виде: • echo gmdate("D, d M Y H:i:s")."GMT"; Last-Modified • "Last-Modified: " HTTP-date • Указывает дату последнего изменения документа. Дата должна задаваться в том же формате, что и в случае с заголовком Expires. Данный заголовок можно не использовать для динамических страниц, так как многие серверы (например, Apache) для таких страниц сами выставляют дату модификации. • Возможно сделать страницу всегда обновленной: • header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); Location • "Location :" абсолютный URL • Полезный заголовок, который перенаправляет броузер на указанный адрес. Его действие сравнимо с META тегом Refresh: • <META HTTP-EQUIV="Refresh" CONTENT="0; URL=someURL"> • Например, этот заголовок может быть использован так: • if ($login != $admin_login) header("Location: http://www.server.com/login.php"); else header("Location: http://www.server.com/admin.php?login=$login"); if (!headers_sent()) exit("Произошла ошибка! Пройдите <a href='http://www.server.com/login.php'>авторизацию</a> заново"); Классы в PHP • Класс служит шаблоном для объекта. Он создается следующим образом: • class Myclass { // определение класса } • class Array_class { var $array = array(); • // Определение свойства function getUniqSum() { • // Получает сумму уникальных элементов • return array_sum(array_unique($this->array)); } • function getSortedMerge() { • /* Возвращает отсортированный массив из ключей и элементов массива */ • $result = array_merge(array_keys($this->array), array_values($this->array)); sort($result); return $result; } } • class Advanced_array extends Array_class { • function advanced_array($size) { • /* заполняет массив подряд идущими числами, чередуя их знаки */ • $z = 1; for ($i = 0; $i < $size; $i++) { • $this->array[$i] = $i *$z; $z = - $z; } • } • function getSizeofMerge() { • /* возвращает число неповторяющихся элементов массива, полученного getSortedMerge() */ • $merge = $this->getSortedMerge(); • return sizeof(array_unique($merge)); } } • $my = new Array_class; $my->array = array(1, 2, 6, 1); echo $my->getUniqSum(); $my = new Advanced_array(4); echo $my->getSizeofMerge(); • создаем новый экземпляр класса Array_class • определяем его свойство array • выводим сумму элементов без учета повторяющихся • создаем экземпляр класса Advanced_array, который наследует все свойства и методы Array_class Основы MySQL