Как выяснилось, многие не совсем понимают принцип работы MaxSite CMS — для них это что-то вроде черного ящика с загадочными хитросплетениями. Предыдущие публикации на эту тему сохранили свою актуальность, хотя с выходом D2 (D3, D4 и default с версии MaxSite CMS 0.90) код изменился и стал несколько проще.
Чтобы закрыть эту тему, попробую на пальцах объяснить такие моменты. Для начала рассмотрим процесс «включения» MaxSite CMS.
MaxSite CMS использует фреймворк CodeIgniter, поэтому в момент запуска происходит инициализация ядра CodeIgniter, где подключаются библиотеки для работы с базой данных и небольшое собственное «ядро». Дальше происходит инициализация контроллера MaxSite CMS.
Входящий URL
Работа CodeIgniter (а значит и MaxSite CMS) происходит в зависимости от входящего запроса. Если это вывод одиночной записи, то в адресе будет page. Для рубрик — category и т.д. Таким образом URL разделяется на сегменты, каждый из которых несёт определённую роль. Первый сегмент может указывать на тип данных. Например в адресе http://сайт/page/about:
- page — предопределенный тип данных, указывающий, что нужно вывести одиночную страницу сайта;
- about — уникальная короткая ссылка этой записи (уникальная среди записей page).
MaxSite CMS в типовом варианте рассчитана на обычные сайты и блоги, поэтому содержит базовый предопределённый набор типов данных и необходимые для их обслуживания функции. Полный комплект типов вы можете самостоятельно посмотреть в application/controllers/maxsite.php в методе _remap, но в целом это привычные page, category, users и т.п.
В контроллере MaxSite CMS происходит только проверка существующих типов и в зависимости от результата управление передаётся в соответствующий view (вьювер, «отображение»), который в свою очередь подключает текущий шаблон сайта.
Также в контроллере происходит загрузка ядра MaxSite CMS — common/common.php. Это означает, что в любой части системы всегда будут доступны функции этого файла. В отличие от других CMS, у нас ядро очень компактное и содержит всего 105 функций, включая служебные.
После загрузки ядра, происходит подключение всех активных плагинов и выполняется хук init. На этом, собственно, вся инициализация и заканчивается — MaxSite CMS полностью подготовила данные и все структуры, которые будут использованы в шаблоне для вывода данных.
«Нулевой» шаблон
Для шаблона существует только одно требование — наличие index.php. Никаких других требований к шаблону нет. Таким образом вы можете без проблем создать шаблон из этого единственного файла и разместить в нём что-то вроде:
Привет!
А если вы разместите строчку
Время: {elapsed_time} | Память: {memory_usage}
— то сможете увидеть потребление PHP-памяти и время выполнения для этой страницы.
Эти спец.коды используются парсером вывода CodeIgniter. Учитывайте только, что на эти показатели влияют активированные плагины. Они подключаются до передачи управления в шаблон.
Диспетчеризация в шаблоне
Понятно, что пустой шаблон не имеет смысла, поэтому в index.php мы размещаем диспетчер типов данных в виде функции mso_dispatcher().
В default-шаблоне диспетчеризация выполняется другим кодом, в котором несложно запутаться. В default вся эта «кухня» убрана в ядро MaxSite CMS.
Диспетчер не просто подключает type-файл, но и выполняет задачу по поиску отсутствующего типа данных. Именно благодаря диспетчеру, добавить произвольный аля-тип проще-простого — помещаем в type-каталог одноименный php-файл.
И тут мы подходим к одному важному моменту — диспетчер не выполняет установку типа данных, он только подключает его файл. Типы данных определяются и задаются в контроллере MaxSite CMS. Поэтому для всех других типов система выставляет универсальный тип page_404, сигнализирующий, что тип данных системе не известен.
Например для адреса http://сайт/book будет выставлен тип page_404, потому что MaxSite CMS не знает как именно обслужить такой запрос и есть ли вообще функции для этого дела.
В шаблоне же, диспетчер, увидев этот тип попытается проанализировать первый сегмент адреса и увидев book, предположит, что для него есть одноименный php-файл в каталоге type. И если есть, то подключит его.
Ну а что именно будет в book.php, зависит уже от самого шаблона и этого файла.
Как добавить свой тип данных?
При текущем диспетчере добавлять свой тип данных не имеет особого смысла — вполне достаточно анализа сегментов URL.
Напомню, что для проверки типа данных используется функция is_type(), а для получения сегмента адреса — mso_segment().
if (is_type('home')) { ... это главная страница ... } if (mso_segment(1) == 'book') { ... первый сегмент равен book ... } if (is_type('book')) { ... всегда будет fasle, поскольку такой тип не известен ... }
Вместе с тем, создать свой тип данных очень просто. В каталоге контроллера нужно разместить одноименный php-файл. Например, чтобы сделать тип book делаем файл application/controllers/book.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); $this->_view_i('book');
Теперь проверять тип данных можно с помощью is_type('book')
.
Работа type-файла
Диспетчер шаблона подключает type-файл, в котором уже определяется алгоритм вывода данных. Если мы посмотрим на шаблон default, то увидим, что каталог type пустой (точнее он есть, но там неподключаемые файлы). Откуда же тогда берутся данные?
В прошлом шаблоны базировались только на type-файлах шаблона Default. Если в шаблоне нет type-файла, то происходило подключение этого файла из default.
В новых версиях MaxSite CMS, type-файлы находятся в shared-каталоге и диспетчер (функция mso_dispatcher) сама решает откуда подключить type-файл. Поскольку в default используется типовой вывод данных, то в нём и нет подключаемых type-файлов.
Вместе с этим фактом, я всё-таки кратко остановлюсь на принципе работы type-файла. Для примера буду ориентироваться на тип page — application/maxsite/shared/type/page/page.php.
В начале type-файл должен получить данные для вывода и, если они есть, то сформировать сам вывод. Получение данных из БД осуществляется с помощью функции mso_get_pages(). В зависимости от параметров она возвращает массив записей для вывода. Если записей нет (например неверная ссылка), то возвращается пустой массив и выводится сообщение о ненайденной странице (404).
Важный момент: данные получаются до их вывода в браузер.
Сам вывод данных размещается между двух файлов:
- main/main-start.php
- main/main-end.php
То есть вначале подключается main-start.php, после выводятся полученные данные из базы, и в конце подключается main-end.php.
Такой вариант позволяет выделить верстку сайта в отдельные файлы, оставив type-файлу только его часть работы.
Чтобы упростить верстку и переместить её в один файл, используется буферизация вывода. В main-start.php она включается, а в main-end.php результат вывода сохраняется в отдельную переменную и подключается файл main.php, где, собственно, и происходит вывод в браузер.
В default находится только main.php, а результат работы type-файла находится в переменной $CONTENT_OUT. Файлы main-start.php и main-end.php в shared-каталоге, где подключаются автоматом.
Впрочем, это еще не всё. Файл main-end.php представляет собой «концовку» type-файла и позволяет подключать разные main-файлы. Например, если нужно сделать main-файл без сайдбара, то в своём шаблоне делаем main/no-sidebar/main.php, где убираем HTML/PHP-код вывода сайдбара. Выбор main-файла — в опциях при редактировании записи.
Примерно также можно задать модульную сетку под произвольный тип данных: main/type/ТИП/main.php. В таких случаях выбор main-файла происходит автоматом.
Main-файлы
В default все «служебные» файлы вынесены в shared-каталог. Остаются только те, с которыми должен работать вебмастер. Смысл появления main-файлов в том, чтобы упростить вёрстку и позволить создавать разные модульные сетки под разные типы данных или для разных записей. На сегодняшний день можно создавать раздельные main-файлы для главной, рубрик, записей, архивов и т.д. В каждом main-файле можно организовать свой набор подключаемых компонентов и свои css-стили. То есть сайт один, а его внешний вид и структура может меняться.
Type_foreach-файл
Рассказ будет неполным без упоминания type_foreach-файлов.
MaxSite CMS строится по принципу «заменяющей функциональности». То есть существует некий функционал, который может быть замещён своим. Например вывод заголовка и информации записи жестко прописан в type-файлах. Когда нужно изменить порядок информации, то пришлось бы каждый раз править этот файл, что не совсем удобно. Механизм type_foreach-файлов позволяет заменять различные участки кода на свои варианты.
В нашем примере достаточно разместить type_foreach/info-top.php, чтобы заменить типовой вывод заголовков записей.
Type_foreach-файлов достаточно много и есть только один способ узнать какой файл за какой отвечает кусок кода — это просмотреть нужный type-файл. MaxSite CMS постоянно развивается и type_foreach-файлы могут как появляться, так и меняться по коду. Так что документировать их будет достаточно проблематично. Особенно следует отметить, что некоторые type_foreach-файлы немного по разному работают в Default-шаблоне и в shared-каталоге.
В целом же сегодняшние шаблоны могут прекрасно обходится только type_foreach-файлами без правки type-файлов. Скажу больше: направление развития MaxSite CMS сейчас в том, чтобы обеспечить еще большую гибкость под разные задачи. Например info-top можно будет подключать по типу данных: info-top-page.php — для одиночных записей, а info-top-category.php для рубрик.
В заключении
Шаблон default смотрится как простой набор файлов/каталогов, которые работают и подключаются неочевидным способом. Цель такого подхода в том, чтобы исключить весь сложный код из шаблона, но при этом оставить возможность менять его произвольным образом, если возникнет такая необходимость. Я уже отмечал, что в других CMS создание шаблона целиком ложится на плечи вебмастера, включая сложный программный код. В MaxSite CMS я стараюсь максимально разделить работу программиста и верстальщика, но при этом обеспечить обоих большим качественным функционалом. Даже «примитивный» default по своим возможностям многократно перекрывает возможности других CMS. Для некоторых — это вообще недостижимый уровень.
Комментариев: 8 RSS
1Аноним15-02-2013 15:50
Максим, большое спасибо за этот урок. Наконец в одном месте собрано почти все по новому шаблону.
Но как самому нетерпеливому, мне бы хотелось задать несколько вопросов:
1. Правильно ли я понимаю что "тип данных" это просто свой личный синоним одного из штатных типов? Т.е. я как бы создаю новый объект который наследует свойства от page или category? Просто некий логический разделитель (такой же как и рубрики, метки, метаполя)?
2. Вы не слова не написали про "тип страниц". По логике это тоже самое что и тип данных (хотя везде написано что их путать нельзя). Значит тип данных умеет нечто такое что не умеет тип страниц? Может быть какой-то из них лишний компонент? Если уж они дублируют логику своего поведения.
3. Про type-файлы. Берем шаблон MAX-EI-EI - type/home - есть папка units - эелементы из нее подключаются автоматом, или только при явном указании в модуле программы?
4. Про type_foreach. Как я понял образцы которые можно использовать в своем шаблоне лежат в shared/blanks/type_foreach - далее подобрать подходящий и необходимо как то настраивать в коде замещение им - или оно на автомате происходит если он есть в папке шаблона?
Вопросов еще много, но я старался задать только относящиеся к теме урока.
Заранее спасибо за разъяснения.
С уважением, Вячеслав
2Аноним15-02-2013 16:05
Тип данных на уровне контролера — это просто предопределенный первый сегмент URL. В системе реализована его обработка и вывод данных. Как и что выводить определяется уже в type-файле. Никакого наследования или объекта типа нет и не может быть. Можно условно сказать, что тип данных определяет вариант алгоритма вывода данных.
Сами написали, что это разные вещи и тут же их смешиваете. :-) Это абсолютно разные вещи.
Не нужно гадать. Разве вы не видите my_home.php?
Это старые type_foreach-файлы к default-шаблону. Некоторые из них несовместимы с shared. Кроме того в этих type_foreach-файлах может использоваться старый код, который не работает в D2. Для определения нужно смотреть type-файл. Пока это единственный верный способ.
3Аноним16-02-2013 08:54
я имел ввиду, что сами данные у нас всегда одни и теже - запись, рубрика. Т.е. мы типом данных просто можем задать персональный вывод на сайт записей.
И для того что бы этот переключатель вывода сработал для нужных записей мы и ставим им тип страниц.. Т.е. тип страниц - логическое разделение записей, а тип данных - логическое разделение способа отображения записей.
Верно я понял ?
А можно попросить какую тему в примерах разобрать не следующем уроке ?
С уважением, Вячеслав.
4Аноним16-02-2013 09:37
Что-то вы меня совсем запутали. Я не знаю, что такое «переключатель вывода». Изъясняйтесь в понятных терминах. Я абстракцию не понимаю.
5Аноним16-02-2013 10:32
Боюсь что правильные термины мне .. сложно подобрать :(
Я написал, как понял.. как я сам себе объясняю отличие типов данных от типа страниц, и для чего они в конечном счете нужны :(
был бы какой-то готовый шаблон который бы показал бы на примере с кодом Вами описанный тип данных book.. но боюсь что это несбыточное желание..
Придеться начинать штудировать лекции с самого начала похоже. Где-от я пропустил важный момент для чего были созданы типы данных и типы страниц.
6Аноним16-02-2013 12:31
Сами придумали себе проблему, сами и решайте. Мне нечего добавить.
7Аноним16-02-2013 18:24
ВОТ!
http://max-3000.com/uploads/maxsite-cms-shema.gif
что после типа данных, что после типа страниц, мы все одно идем к вьюверу..
т.е. они практически делают одно и тоже.. но почему-то выделены по отдельности..
получается, что тип данных может позволять "объединять" вывод разных типов страниц..
а в прочем Вы правы, я наверное слишком зациклился на этом, есть куда более интересные загадки - например почему page_out не универсален для вывода записей любого типа данных, а зашит по умолчанию только на page
С уважением, Вячеслав
8Аноним17-02-2013 08:42
Как обычно вы всё перепутали. Неужели так сложно внимательно прочитать статью и мои комментарии? Если непонятно, см. исходный код. Не нужно ничего придумывать.