Портал для веб-мастера
Вход пользователей
Поиск статей
WoWeb.ru » Статьи » Программирование для Web » PHP

Долой процедурное программирование, даешь объектно-ориентированное!

Программисты - народ ленивый. Поэтому, когда дело доходит до работы, они сначала ищут в сети какой-нибудь программный продукт, который в той или иной степени удовлетворяет их потребности в решении поставленной задачи. Если программист пишет что-то на PHP, то одной из первых систем, которые он найдёт, будет PHP Nuke. Поигравшись с ним некоторое время, программист понимает, что вещь, конечно, хорошая, но слишком уж "коряво" написанная, тяжело адаптируемая к задачам, отличных от web-портала, да и перевод на русский язык сделан человеком, имевшем не более трёх очков по великому могучему.

Тем не менее, подход к хранению кода в том виде, как это реализовано в PHP Nuke и описано на большом количестве сайтов, посвящённым PHP, кажется вполне логичным, доступным и приемлемым.

Общая схема этого похода, называемого "модульным", такова: Существует некий главный скрипт, например index.php. Этот скрипт в неком параметре, например, $module, принимает имя модуля, который отдаёт браузеру какую-нибудь страницу. index.php выглядит примерно таким образом:

<? include "config.php"; if (!$module || !file_exists("modules/$module.inc.php")) { $module="default"; } include "modules/$module.inc.php"; ?> 

Типичный "модуль" при таком построении сайта выглядит так:

<? if (!eregi("index.php", $PHP_SELF)) { die ("Access denied"); } $page_title="..."; // устанавливаем имя страницы include "includes/header.php"; // подключаем дизайн // некий <a href="/php">php</a> - код, который генерирует данную страницу include "includes/footer.php"; // подключаем остатки дизайна ?> 
Вроде бы всё хорошо, однако есть некоторые но:
  1. В каждом модуле нужно делать include заголовка - иначе не сможем изменить <title> и другие тэги в начале страницы.
  2. В каждом модуле необходимо делать
    if (!eregi("index.php", $PHP_SELF)) { die ("Access denied"); }
    - чтобы не вызвали напрямую, миновав различную инициализацию переменных, подключение к СУБД, include общих функций и т.д. в config.php. Хотя, на самом деле, такой запрет делается тремя строчками в .htaccess:
    <files *.php> deny from all </files> 
  3. В каждом модуле надо делать include нижней части страницы - по той же причине, что и п.1
  4. При программировании модулей приходиться многократно вызывать одни и те же процедуры: генерацию меню, навигации, баннеров, голосований и т.д. Даже если все эти процедуры будут с красивыми, легкозапоминаемыми именами, с небольшим количеством параметров, будут содержать всё HTML-форматирование внутри себя, то всё равно каждый раз при написании модуля надо будет последовательно написать вызовы всех этих процедур:
    <? PageNavigation(module params); PageLeftMenu(module params); // PHP-код, генерирующий контент PageRelatedLinks(module params); PageNewsLinks(module params); PageVotes(module params); PageBanner(module params); ?> 
  5. Другие но, забытые как страшный сон
Таким образом, написание нового модуля начинается с копирования текста старого модуля с последующим исправлением блока, ответственного за контент.

Однако есть способ избавить себя от этого монотонного, длительного и никому не нужного процесса - для этого нужно вспомнить о существовании ООП (объектно-ориентированного программирования) и о том, что PHP очень неплохо это самое ООП поддерживает.

Для начала создадим класс - Web-страницу, в которой опишем все функции, используемые при генерации наших страниц:

class WebPage { // если имя функции совпадает с именем класса, то она считается конструктором // говоря по-русски, она выполняется при создании объекта function WebPage() { $this->page_title="демо-модуль"; } function PageHeader() { include "includes/header.inc.php"; // в этом файле вместо <?=$page_title;?> надо будет написать <?=$this->page_title;?> } function PageFooter() { include "includes/footer.inc.php"; } function PageNavigation() { // Код для навигации } function PageLeftMenu() { // Код для меню в левой части страницы } function PageContent() { // Код, генерирующий контент } function PageRelatedLinks() { // Код, генерирующий ссылки на связанные разделы } function PageNewsLinks() { // Код, генерирующий блок новостей } function PageVotes() { // Код, генерирующий блок голосований } function PageBanner() { // Код, генерирующий баннер } function Run() // ф-я Run последовательно вызывает все необходимые  // методы класса WebPage для построения страницы { $this->PageNavigation(); $this->PageLeftMenu(); $this->PageContent(); $this->PageRelatedLinks(); $this->PageNewsLinks(); $this->PageVotes(); $this->PageBanner(); } } ?> 
Теперь, если нам надо сделать, например, страницу, которая отличается от стандартной только блоком контента, то мы можем определить новый класс, производный от WebPage:
class CoolPage extends WebPage { // переопределяем конструктор, чтобы изменить имя модуля function CoolPage() { // вызываем конструктор родительского класса - вдруг он что-то полезное делает? ;) parent::WebPage(); $this->page_title="Крутой модуль"; } function PageContent() { // выводим контент } } 
если нам на странице не нужны новости, то мы определяем другой класс:
class CoolPageWithoutNews extends CoolPage { // здесь мы не описываем функцию CoolPageWithoutNews  // в этом случае PHP автоматически вызовет конструктор родительского класса // соответственно имя нашей страницы будет "крутой модуль" function PageNewsLinks() { // тут пусто, чтобы ссылки на новости не выводились } } 
и так далее.

В принципе, если у вас появляется большое количество классов, то код каждого из ни их тоже можно разместить в отдельном файле, однако следует следить за тем, чтобы классы, у которых есть производные классы, были доступны всегда, иначе PHP не сможет понять, из какого файла брать код родительского класса.

Вот пример файла index.php, который может выступать в качестве "главного файла":

<? include "config.php"; include "base_classes.php"; if ($module && file_exists($file="modules/$module.inc.php")) { // проверяем, есть ли файл с "телом" класса include $file; } if (!class_exists($module)) { // проверяем, что класс существует $module="WebPage"; } $page=new $module; // создаём объект $page->Run(); // запускаем генерацию страницы } ?> 
Примечание: не смотря на то, что весь приведённый выше код ни разу не запускался, вышеуказанная технология, с той разницей, что почти вся информация находится в БД, реально эксплуатируется, например, на моём сайте - dmitry.rsl.ru
Автор: Дмитрий Верещака · Добавлена: 2003-09-08
Просмотров: 3259 · Рейтинг: 5.0

Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Категории раздела
Flash
Apache
WWW
PhotoShop
Веб-дизайн
Раскрутка и реклама
Базы данных
3D графика
Хостинг
Истории веб-мастеров
Web-технологии
Сетевая безопасность
Программирование для Web
Операционные системы

Новые статьи
Лучшие статьи
Популярные статьи
Комментируемые статьи
Разделы сайта
Скрипты
Статьи
Шрифты
Флэш исходники
HTML шаблоны
Партнерки
Клипарты
Смайлы
Фоны
Гифы
Иконки
Опрос сайта
Ведете ли вы блог?
Всего ответов: 60121
Наша кнопка
WoWeb.ru - портал для веб-мастера