Генератор данных
Конечно, это еще далеко не весь сценарий. Вы, наверное, заметили, что сердце шаблона — цикл foreach вывода записей — использует непонятно откуда взявшуюся переменную $Book, по контексту — двумерный массив. Кроме того, при отправке формы тоже ведь нужно предусмотреть некоторые действия (а именно, добавление записи в книгу).
Мы видим, что где-то должен быть скрыт весь этот код. Он, действительно, располагается в отдельном файле с именем gbook.php. Отличительная черта этого файла — то, что в нем нет никакого намека на то, как нужно форматировать результат работы сценария. Именно поэтому я называю его генератором данных (листинг 30.2).
Листинг 30.2. Генератор данных: gbook.php
<?
define("GBook","gbook.dat"); // имя файла с данными гостевой книги
// Загружает гостевую книгу с диска. Возвращает содержание книги.
function LoadBook($fname)
{ $f=@fopen("gbook.dat","rb"); if(!$f) return array();
$Book=Unserialize(fread($f,100000)); fclose($f);
return $Book;
}
// Сохраняет содержимое книги на диске.
function SaveBook($fname,$Book)
{ $f=fopen("gbook.dat","wb");
fwrite($f,Serialize($Book));
fclose($f);
}
// Исполняемая часть сценария.
// Сначала — загрузка гостевой книги.
$Book=LoadBook(GBook);
// Обработка формы, если сценарий вызван через нее.
// Если сценарий запущен после нажатия кнопки Добавить...
if(!empty($doAdd)) {
// Добавить в книгу запись пользователя — она у нас хранится
// в массиве $New, см. форму в шаблоне. Запись добавляется,
// как водится, в начало книги.
$Book=array(time()=>$New)+$Book;
// Записать книгу на диск.
SaveBook(GBook,$Book);
}
// Все. Теперь у нас в $Book хранится содержимое книги в формате:
// array (
// время_добавления => array(
// (или id) name => имя_пользователя,
// text => текст_пользователя
// ),
// . . .
// );
// Вот теперь загружаем шаблон страницы.
include "gbook.htm";
?>
Как видим, исполняемая часть довольно небольшая и, действительно, занимается лишь подготовкой данных для их последующего вывода в шаблоне. Шаблон рассматривается этой составляющей как обычный PHP-файл, который она подключает при помощи инструкции include. Ясно, что весь код шаблона (хотя его и очень мало) выполнится в том же контексте, что и генератор данных, а значит, ему будет доступна переменная $Book.
Логически весь код можно разбить на 3 части. Первая из них — задание конфигурации сценария, в нашем случае она состоит всего лишь в определении одной-единственной константы GBook, хранящей имя файла гостевой книги. Во второй части, которую можно назвать "прикладным интерфейсом" гостевой книги, содержатся описания функций, достаточных для работы с гостевой книгой. Это, конечно, функции загрузки и сохранения наполнения книги на диске. Наконец, третья часть генератора данных обрабатывает запросы пользователей на добавление данных в книгу.
Таким образом, для работы нашего сценария нужны три файла: генератор данных, шаблон книги и файл с записями книги. В принципе, это минимум, если только не привлекать для хранения записей базу данных (что, безусловно, лучше в больших программах). Однако в нашем случае проще как раз работать с файлами, поэтому я на них и остановился.
Обратите внимание: для того чтобы теперь переделать гостевую книгу так, чтобы она использовала базу данных, а не файл, достаточно изменить всего лишь 2 функции: LoadBook() и SaveBook(). Ни других частей генератора данных, ни, тем более, шаблона это не затронет. На самом деле, такой подход не является случайностью: он очень тесно связан с трехуровневой схемой построения интерактивных сценариев, о которой мы скоро будем говорить.