Как я писал свою CMS

Еще во времена учебы у меня был опыт написания веб админок для кастомных проектов (например формы для базы данных).

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

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

Забегая вперед, могу сказать, что все я выполнил в срок и в полном объеме, а после чего на этом же движке сделал десятка два коммерческих сайтов.

В данном материале я попробую вспомнить и воспроизвести путь написания этой CMS, буду отмечать какие задачи передо мной стояли и как именно я их решил.

    Сразу отмечу какой функционал был решен:
  • 1) Создание многоуровневых меню и их сегментация по сайту.
  • 2) Шаблоны для страниц
  • 3) Псевдо шаблонизатор для контента
  • 4) ЧПУ
  • 5) Файловый менеджер
  • 6) Функциональные блоки
  • 7) Поддержка нескольких языков
  • 8) Модуль регистрации и управления пользователями
  • 9) Модуль гостевой книги
  • 10) Различные формы

Первые семь пунктов формируют ядро CMS, остальное это модульная функциональность, которая может подключаться и отключаться отдельно.


Первое, что надо было решить - хранение структуры сайта и рендеринг страниц.

    Требования были такие:
  • 1) нужна была возможность создавать сколь угодно вложенные менюшки
  • 2) при этом должна быть возможность сегментировать менюшки (верхнее меню, боковое и так далее), причем делать это безлимитно.
  • 3) явное и понятное управление структурой сайта

Для хранения структуры было решено использовать иерархическую структуру данных вида parent-child. Это позволяло уже на уровне данных хранить сколь угодно глубокие разделы меню. Разумеется нужна была возможность сортировки страницы на одном уровне.

таблица link

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

структура сайта

Я решил, что все управление содержимым сайта будет происходить только в админке. Поэтому сразу разграничил скрипты на отображение контента, и на его редактирование.

Вообще я применял ооп подход в написании кода, но это было ооп ради ооп, никакого профита я из него не извлек, просто использовал синтаксис.

И тем не менее я создал класс classSite.php, который должен был заниматься рендерингом всего сайта, и разумеется был класс classAdmin.php, который включал в себя весь админский функционал.
На на самом деле конечно только двумя файлами не обошлось, были вспомогательные классы (например на каждый модуль), но эти основные.

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

таблица page

    Сама страничка разумеется имеет ряд полезных свойств:
  • 1) Название в меню
  • 2) Шаблон для страницы
  • 3) Заголовок страницы (title)
  • 4) Мета теги
  • 5) Возможность скрыть ее из меню
  • 6) Установить длительность активности
  • 7) Двуязычность

редактирование страницы

Вообще изначально планировалось иметь сколь угодно языков добавляемых через админку, но из-за ограничения по времени остановился на двух. Кроме того многоязычность можно было решить другим способом (шаблонами).

Меню для сайта формирется рекурсивной функцией, которая пробегает по всему дереву связей parent-child и создает статичный html файл, который инклудится на месте меню. Разумеется тем самым создается полное меню (за исключением страниц, помеченных, как невидимые).

Данная фнкция срабатывает каждый раз, как меняется структура сайта из админки. В самой же админке структура генерируется каждый раз динамически. html код меню сразу содержит ul li список и все необходимые классы, вроде .item_menu или .active_item_menu при переходе по страницам, так что визуально обрамлять его можно, как угодно.

Подменюшки генерируются каждый раз при рендеренге страницы. Я не стал их кешировать, потому что это все это лишь один SQL запрос.


Шаблоны.

Шаблоны должны были позволять создавать для каждой страницы уникальный дизайн при необходимости. Думаю все знают, что это такое и зачем это нужно. Ни одна CMS без этого обойтись не может.

раздел шаблонов

Решалось все достаточно просто, в админке был сделан специальный раздел для создания редактирования шаблонов. Каждый шаблон имеет название, внутренние имя, картинку при необходимости и конечно же свой уникальный дизайн (html, css, js).

Каждой странице присваивался какой то шаблон, если это не четко заданный, то шаблон по умолчанию, который выставлялся из раздела шаблонов.

При рендеренге страницы цеплялись необходимые файлы из соответствующего шаблона.

редактирование шаблона


Шаблонизатор.

Все наверное знают, что такое шаблонизатор для кода, например SMARTY.
Данная вещь позволяет отделить php (логику) код от html кода.

Например в месте дизайна, где нам надо вставить контент или форму, вместо php кода мы пишем {CONTENT} после чего при рендеренге страницы шаблонизитор заменит {CONTENT} на содержимое страницы.

На тот момент я даже не представлял о существовании MVC, но уже было понятно, что html и php надо как то разделять.

Мой подход был не совсем классический, я знал, что можно сделать плейсхолдеры (это как раз такие штуки {}), но мне не хотелось терять в ресурсах на обработке содержимого, тогда мне по крайней мере так казалось, поэтому я решил задачу в лоб, на месте нужного мне функционала в коде html писался нужный метод, например $site->content(), вроде не на много сложней и длиньше, и экономит ресурсы, но в последствии это вызвало некоторые сложности с прикреплением визивик редактора.


Общая логика рендеринга страницы.

Как я писал ранее, существует класс slassSite.php, по моей задумке он должен был олицетворять объект "сайт", и владеть всем функционалом для его отображения и обработки меню. Конструктор класса подключался к базе данных.

content() - отображает содержимое текущей страницы.
  • title() - заголовок страницы
  • meta() - мета данные
  • menu() - показывает основное меню со всей его вложенностью
  • subMenu("parent") - показывает пункты меню, которые принадлежат parent
  • И многое другое, функционал дописался очень просто на основе имеющихся данных в базе.

      При входе в класс site:
    • Происходит подключение к базе
    • Определение языка
    • Определение текущей страницы через GET переменную
    • Выборка свойств страницы
    • Подтягивание файлов шаблона
    • Ну и далее уже обрабатывались методы, которые расставлены в коде шаблона

    Чпу.

    Тут все просто, применил модуль апача mod_rewrite.

    редактирование .htaccess


    Файловый менеджер.

    Сразу было понятно, что без него не обойтись.
    Написан он был довольно просто, без богатого функционала, но со своей задачей справлялся.

      Я решил разделить файловый менеджер на две части:
    • 1) Раздел шаблонов. Что бы можно было дополнят шаблон файлами или удалять лишнее.
    • 2) Раздел ресурсов. Это основное место хранение дополнительных файлов для сайта. То есть весь контент, кроме текста страниц (который хранится в отдельном каталоге) должен был прибывать тут.
      Из функционала есть:
    • 1) Просмотр файлов, тип файла, размер файла.
    • 2) Путешествие по иерархии каталогов
    • 3) Создание папок
    • 4) Загрузка файлов

    файловый менеджер


    Функциональные блоки.

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

    функциональные блоки

    Суть функциональных блоков сводится к тому, что можн вставлять произвольный код (не важно какой php, html, js или просто текст) для определенных страниц в определенном месте.

    Например нам надо, что бы в левой колонке шаблона под новостями на странице "Наши услуги" выводилась карта. Это можно решить созданием дополнительного шаблона, а можно просто сделать блок и добавить его в шаблон страницы $site->block("map").

    Блоки создается в отдельном разделе админке, где им присваивается имя, код и указываются страницы на которых они активны.

    редактирование блока


    Модули.

    Ну тут все относительно просто.

    Это дополнительный фнкционал, который не привязывался к базовой структуре сайта, то есть не влиял на ее работу, и выполнял какие то свои задачи.

      Модулями были:
    • 1) Регистрация и управление пользователями
    • 2) Формы заказов
    • 3) Голосовалки
    • 4) Отчеты и так далее.

    Вот примерно так и работает мой движок.
    Как я говорил в начале, писался он очень давно, когда у меня было мало опыта и понимания некоторых вещей, сейчас бы конечно многое было бы сделано иначе.


    comments powered by Disqus