Всего три файла - и гостевая книгаА можно даже два
Рисунок 9.2. Всего три файла - и гостевая книга. А можно даже два

Содержимое же файла niz.php (см. Рисунок 9.2) может быть таким (пояснения относятся к коду под ними):
<?php
Укажем имя папки, в которой будут сохраняться отзывы (ее, разумеется, вначале надо будет создать на аккаунте сайта вручную). Само имя может быть любым - важно лишь, чтобы оно не содержало пробелов или специальных символов:
$dirct="gb";
Ну а далее следует уже знакомый вам сценарий "Папкопотрошилки" , применяемый к этой самой папке с отзывами. Вот практически точно такой же, как и в "Папкопотрошилке", код, записывающий в массив $а[] имена всех файлов, в имени которых содержится указанный выше индекс книги:
$hdl=opendir($dirct) ;
while ($file = readdir($hdl))
if (strstr($file, $nom)!=False)
$a[]=$file;
closedir($hdl);
Примечание:
Функция strstr ищет в своем первом аргументе строку, указанную вторым аргументом, и возвращает True, если ее там находит.
Теперь отсортируем полученный массив. Для этого сначала узнаем количество сообщений книги:
$l=sizeof($a);
а затем, в том случае, если сообщения в книге есть, произведем сортировку (если сообщений нет, т. е. массив $а пуст, то функция сортировки выдаст ошибку, а дальнейшая работа с элементами массива вообще бессмысленна - поэтому нужна проверка размера массива):
if ($l!=0)
{
rsort($a);
Теперь массив $а содержит имена файлов с сообщениями, причем в первых элементах массива содержатся имена файлов с наибольшими номерами (т. е. самые новые - как и следует из приведенного выше алгоритма). Если же требуется обратный порядок (т. е. чтобы новые сообщения помещались в конец страницы), то вместо функции rsort (сортировка по убыванию) следует использовать функцию sort (т. е. сортировка по возрастанию).
Ну и, наконец, вставим все файлы с сообщениями в страницу с гостевой книгой с помощью оператора include, перебрав последовательно элементы массива с именами этих файлов конструкцией foreach:
foreach ($a as $value)
{
include ("$dirct/$value");
echo ("<br>(разделитель сообщений)");
Как уже говорилось, foreach считывает в указанную в его параметрах переменную - в данном случае $value - все элементы массива - в данном случае $а - по очереди, выполняя каждый раз указанный после него в фигурных скобках код, в котором указанная переменная может использоваться. Поскольку в массиве первыми идут элементы с именами файлов с наиболее новыми сообщениями, то и на странице эти сообщения появятся сверху.
Комментарий:
Оператор foreach будет работать только в РНР 4.0 и выше. Если вы можете использовать лишь РНРЗ, то вместо него можно использовать цикл for, указав в его параметрах величину массива $1:
for ($k = 1; $k < $1; $k++) {
Для удобства можно записать значение очередного элемента массива в переменную: $value=$a[$k] ;
Все - код вывода имеющихся сообщений завершен!
}>
Теперь осталось разместить на странице форму для добавления нового сообщения. В ее заголовке укажем имя файла, в котором будет размещен код добавления нового отзыва - допустим, это otziv.php:
<form method="post" action="otziv.php">
Чтобы обойтись одним файлом-обработчиком новых отзывов, передадим ему в скрытом поле формы индекс гостевой книги - чтобы обработчик знал, к какой книге относится переданное ему сообщение. Для удобства назовем его так же, как и переменную, содержащую индекс - nom.
<input name="nom" type="hidden" value="<?php echo $nom; ?>">
Комментарий:
Скрытое поле (типа hidden) не отображается в браузере, однако передается вместе с формой.
Ну и - непосредственно поле ввода сообщения, уже, ясное дело, не скрытое:
<textarea name="otziv" cols="60" rows="10" wrap="virtual"></textarea>
И вездесущая кнопка отправки формы:
<input name="submit" type="submit" value="Добавить отзыв"></form>
Теперь осталось сделать программу-обработчик новых отзывов. Как это ни удивительно, но она уместится всего в пять строк. Разместить ее надо в том файле, имя которого указано в заголовке формы для ввода сообщения - в нашем случае это otziv.php (см. Рисунок 9.2).
<?php
Укажем сценарию имя папки с отзывами:
$dirct="gb";
В принципе, можно было бы это имя и передать через форму с помощью скрытого поля - типа hidden. А можно было бы и вообще не запоминать в переменную - указывать в сценарии в нужных местах само имя папки (т. е. "gb" в нашем случае) - и дело с концом. Просто так несколько нагляднее, да и в случае необходимости изменить это имя проделать данную операцию будет достаточно лишь в этом месте.
Сгенерируем имя для нового файла с сообщением - просто соединим вместе индекс гостевой книги и временную метку Unix, полученную функцией time():
$otznam=$nom.time();
Как вы помните, при передаче сценарию РНР информации через форму значения ее полей записываются в переменные, имена которых соответствуют значениям параметров пате этих полей, поэтому индекс гостевой книги, переданный через поле формы с именем пот, и оказался в переменной Snom.
Теперь создадим новый файл со сгенерированным именем и откроем его для записи - все это делается одной командой - f open с параметром w+.
Примечание:
Для того чтобы из программы на РНР считать содержимое какого-либо файла или записать в него данные, этот файл нужно сначала открыть - командой fopen (так уж устроен РНР). При этом открытому файлу присваивается некое "внутреннее имя" - так называемый дескриптор, и именно его возвращает функция fopen. Первый параметр fopen - имя файла (вместе с относительным или абсолютным путем к нему), второй — способ открытия файла.
В зависимости от второго параметра функции fopen файл может быть открыт по-разному - для чтения, для записи, с очисткой содержимого или без таковой. Возможные параметры fopen такие:
• r - открыть файл только для чтения и приготовиться читать его с начала.;
• r+ - открыть файл для чтения и для записи и приготовиться работать с ним с его начала;
• w - открыть файл только для записи, предварительно удалив из него все содержимое, причем если файл с указанным именем не существует, то создается новый файл с таким именем;
• w+ - открыть файл как для записи, так и для возможного последующего чтения, предварительно удалив из него все содержимое, причем если файл с указанным именем не существует, то создается новый файл с таким именем;
• а - открыть файл только для записи и приготовиться дописывать данные в его конец. Если файл с указанным именем не существует, то создается новый файл с таким именем;
• а+ - открыть файл для записи и для чтения и приготовиться дописывать данные в его конец. Если файл с указанным именем не существует, то создается новый файл с таким именем.
Открываемый файл может располагаться и на удаленном сервере - в этом случае он будет доступен только для чтения независимо от параметров открытия файла. Путь к файлу в таком случае следует указывать полностью - начиная с http://muftp://.
(В нашем случае можно также использовать параметр а+ - различие этих двух параметров, заключающееся в том, что fopen с параметром w+ очищает все содержимое открываемого файла, a fopen с параметром а+ нет, несущественно, так как файл все равно создается новый):
$hdl = fopen("$dirct/$otznam", "w+");
Проводить операции записи или чтения из файла средствами РНР можно только через дескриптор этого файла - некое "внутреннее имя", "поток вывода данных". Именно дескриптор, а не имя файла, придется указывать в функциях, совершающих эти действия. Дескриптор создается при открытии файла функцией fopen, которая его и возвращает -в данном случае он записывается в переменную Shdl.
Теперь запишем в открытый файл отзыв (находящийся в переменной Sotziv - именно такое имя имело поле ввода отзыва в форме для его ввода), предварительно убрав из него специальной командой, возможно, содержащиеся в нем тэги HTML и команды РНР - дабы обезопасить сайт от действий злоумышленников:
fwrite($hdl,strip_tags($otziv));
Примечание:
Команда fwrite (дескриптор файла, записываемая в файл строка) записывает указанную во втором параметре строку в файл, дескриптор которого указан в ее первом параметре.
То место в файле, с которого совершается чтение данных и в которое осуществляется запись, называется указателем файла. (Если файл представить как тетрадь, то указатель - это открытая страница, вернее, номер открытой страницы.) При открытии файла командой fopen с параметрами r, r+, w или w+ указатель файла ставится на его начало, а при открытии с параметром а или а + -в самый конец.
При записи в файл командой fwrite в том случае, если указатель находится не в конце файла, записываемые данные пишутся поверх имеющихся. Если же файл был открыт командой fopen с параметром а или a +, то вне зависимости от позиции указателя запись в файл идет в его конец, т. е. - после всех данных файла.
Функция strip tags (строка) вырезает из строки, указанной в ее параметрах, все тэги — т. е. "все в угловых скобках", как HTML, так и РНР, ASP и другие, возвращая эту строку с вырезанными тэгами. Если какие-либо тэги вырезать не следует, то их можно перечислить во втором параметре данной функции: команда
strip_tags (строка, ' <a><b><ixu> ') ;
вырежет из указанной в первом параметре строки все тэги, кроме <а>, <Ь>, </>, <и>, т. е. оставит посетителю возможность оформлять ими свой текст.
В результате злоумышленник не сможет разместить в гостевой книге ни HTML-текст, ни PHP-программу, а значит, не сможет ни испортить дизайн сайта, ни выполнить на нем какие-либо свои команды РНР.
Вместо полного удаления всех тэгов из отзыва можно провести конвертацию содержащихся в нем специальных символов - угловых скобок, кавычек, амперсандов - в их эквиваленты, просто отображающие эти символы на экране. Это делает команда htmlspecialchars:
fwrite($hdl, htmlspecialchars($otziv));
Примечание:
Функция htmlspecialchars (строка) конвертирует все "специальные символы" в указанной в ее параметре строке в так называемые "мнемоники HTML", которые отображаются браузером на странице как эти самые символы. Конвертация происходит следующим образом:
• & (амперсанд) заменяется на сочетание символов &атр;
• " ( двойная кавычка) заменяется на сочетание символов " ;
• < (меньше) заменяется на сочетание символов &11 /
• > (больше) заменяется на сочетание cимволов > ;
Сочетания символов "&атр;", """, "<", ">" отображаются в браузере как амперсанд, двойная кавычка, знаки "меньше" и "больше" соответственно.
В РНР третьей (начиная с подверсии 3.0.17) и четвертой (начиная с подверсии 4.0.3) версий в качестве второго аргумента можно также указать параметр ENTjQUOTES или ENTNOQUOTES. Если указан первый, то помимо вышеуказанных замен выполняется еще и замена символа ' (одинарной кавычки) на сочетание символов ', а если указан второй - то никакие кавычки не заменяются.
В результате все тэги будут отображаться на экране точно так же, как при их вводе в поле ввода сообщения - т. е. не станут обрабатываться браузером или интерпретатором РНР.
Комментарий:
Любую информацию, запрашиваемую от посетителя и впоследствии выводимую на какую-либо страницу, весьма желательно перед выводом обработать какой-нибудь из этих функций, htmlspecialchars или strip_tags, - для обеспечения устойчивости сайта к взлому. Ибо даже в том случае, если вы на одной странице запрашиваете у посетителя e-mail, а на другой - его выводите на страницу, злоумышленник в поле ввода e-mail'a может поместить код на РНР, и тогда, будучи включенным в выведенную страницу без какой-либо обработки, этот код благополучно исполнится! А ведь в этом коде может быть что угодно - вплоть до команд удаления файлов. Поэтому не забывайте обрабатывать данными функциями все информацию, что была введена в элементы формы и будет отображаться на какой-либо странице.
Даже скрытые поля и выпадающие списки могут нести в себе угрозу безопасности сайта - если получаемая из них информация выводится на экран. Ничто не мешает злоумышленнику сделать локальную копию страницы с формой на своем жестком диске, прописать в качестве страницы-обработчика полный путь к ней - вместе с адресом сайта и изменить в форме содержимое любых полей, в том числе и скрытых, поместив туда PHP-код. Так что будьте бдительны!
Если Вы желаете, чтобы при отображении на странице сообщений сохранялась их разбивка отправителями на абзацы, то обработайте записываемое в файл сообщение командой nl2br для конвертации символов конца строки в тэги <br>, которые этот разрыв строки и означают:
fwrite($hdl,nl2br(strip_tags($otziv)));
или, если хотите, запишите все команды обработки записываемого сообщения в две строки:
$otziv=nl2br(strip_tags($otziv)); fwrite($hdl,$otziv);
Примечание:
Функция nl2bг (строка) вставляет перед каждым символом начала строки, встреченном в строке в ее параметре, тэг <br> -в РНР версии до 4.0.5, или <Ъг /> - в РНР более поздних версий. (Последний тэг совместим и с языком XML.)
Файл можно закрыть - и закончить сценарий.
fclose($hdl);
?>
Такой код будет работать в РНР версии 3. В РНР версии 4 и выше с этим кодом тоже проблем не будет, однако лишь в том случае, если в конфигурационном файле РНР установлена как on опция register_globals. Настройка данного файла - прерогатива администратора web-сервера (хотя по умолчанию данная опция включена). Если register_globals установить в off, то переменные формы по их именам в сценарии-обработчике доступны не будут.
Однако все переменные, передающиеся через форму, записываются еще и в специальный массив - с именем $HTTP_POST_VARS (если передача произведена методом post - т. е. в адресной строке значения передаваемых переменных не отображаются; вид передачи указывается в заголовке формы) или $HTTP_GET_VARS (если передача произведена методом get-с отображением в адресной строке передаваемых переменных). В РНР4 так происходит всегда, а в РНРЗ - только в том случае, если в конфигурационном файле РНР (настраиваемом администратором web-сервера) установлена как on опция track_vars. Элементы этих массивов названы именами этих переменных; так, переменная, указанная в поле с именем otziv формы, передающей введенные в нее значения методом POST сценарию в файле scen.php, будет доступна в этом сценарии в элементе массива $HTTP_POST_VARS['otziv'].
Поэтому для того, чтобы не зависеть от настройки РНР администратором сервера, вышеприведенный код можно переписать, используя в нем вместо имен переменных формы - элементы массива, поименованные как эти элементы формы. В таком случае он будет выглядеть следующим образом:
<?php
$dirct="gb";
$otznam=$HTTP_POST_VARS['nom'].time();
$hdl = fopen("$dirct/$otznam", "w+");
fwrite($hdl,nl2br(strip_tags($HTTP_POST_VARS['ot ziv1])));
fclose($hdl);
?>
Начиная с РНР версии 4.1, кроме массивов $HTTP_POST_VARS и $HTTP_GET_VARS, программе на РНР доступны идентичные им массивы $_POST и $_GET, так что в том случае, если на сервере, где должны быть размещены ваши сценарии, установлен РНР этой или более старшей версий, то вы можете использовать и такие имена.
Версию РНР вы можете узнать, включив в сценарий команду phpinf о ();. Она даст исчерпывающую информацию как по этому, так и по множеству других вопросов.