Контент


Своя CMS: темы

Наверное каждый, кто писал свою ЦМСку, сталкивался с необходимостью реализации работы с темами. Под темой я понимаю набор ресурсов, определяющих внешний вид приложения (шаблоны, стили, картинки, возможно и js). Я не собираюсь тут выкладывать очередной класс для работы с темами, а просто приведу некоторые свои соображения на этот счет.

Итак, как обычно реализовываются темы. Конечно, сперва создается отдельный каталог themes. Каждая тема хранится с отдельной директории (названной согласно имени темы), и уже в ней выделяются папки по специализациям: views, styles, scripts, images и т.д. (иногда стили, скрипты и картинки объединяют в media). Иногда добавляют специальные файлы с описанием темы или создают целые папки config.

И вот тут-то начинается самое интересное. Сама по себе папка с темами начинает нам напоминать отдельную папку modules, где в роли модулей выступают отдельные темы. Действительно, удобно использовать встроенные возможности поиска нужных ресурсов (особенно с учетом того, что темы могут быть подключены в составе отдельных модулей). В результате помимо «рабочих» модулей (т.е. модулей, отвечающих за функционал приложения) появляются модули второстепенные, так сказать для «красивостей».

Конечно, бессмысленно добавлять все имеющиеся (проинсталлированные) темы в качестве модулей. Ведь все равно пользователь будет обращаться к ресурсам одной темы, ее-то и надо добавлять. Ну, еще можно после нее дописать дефолтную тему. Если что-то не найдено в текущей теме — ищем в теме по умолчанию. Примерно так и поступают в большинстве случаев (по крайней мере, в тех проектах на Kohana, что я видел). Какие я вижу проблемы?

1. Увеличение количества подключенных модулей приведет к замедлению работы приложения. Действительно, даже при условии, что модули тем будут подгружены после всех «рабочих» модулей и не будут участвовать в поиске различных системных классов (до них просто не дойдет дело), сами ресурсы тем будут найдены только после «ворошения» заранее неподходящих для этого системных путей (APPPATH, SYSPATH, модули типа Database/ORM и т.д.).

2. Кеширование путей. Как мы знаем, основной метод, отвечающий за поиск файлов проекта — Kohana::find_file(). Он позволяет кешировать информацию о соответствии относительного и абсолютного путей файлов, что ускоряет работу при последующих обращениях к данному файлу. А теперь давайте подумаем, что будет, если два пользователя откроют страницу, требующую представление ‘template/page‘? Тот, кто обратится раньше, найдет ее по адресу MODPATH/theme1/views/template/page.php (тут я предположил, что выбранная им тема находится в директории theme1). Данная информация сохранится к кэше, и теперь уже второй пользователь, независимо от настроенной темы, будет использовать представление из темы theme1.

Что можно предложить? Первая проблема заключается в отсутствии возможности указать Kohana на диапазон модулей, в котором искать файлы. Было бы хорошо, если бы Kohana::find_files() располагала дополнительным необязательным параметров $modules, в котором можно указать перечень модулей для поиска. Ну или хотя бы менять значение защищенного свойства Kohana::$_paths, в котором система хранит абсолютные пути к модулям в нужном порядке. В принципе, данный класс можно расширить (создаем APPPATH/classes/kohana.php и вперед), но правильно ли? Это ведь один из главных системных файлов… Зато наличие метода, управляющего текущим значением свойства $_paths (а то и просто указание свойства $_paths как public), позволит облегчить работу с дополнительными модулями (кроме тем сразу в голову приходят и плагины — механизм в принципе тот же).

Почему собственный файл kohana.php я предлагаю создать в APPPATH? Дело в том, что загружается kohana.php из файла index.php (т.е. из нашего фронтенда) — ДО отработки bootstrap.php. Значит модули отпадают. В самом фронтенде прописано подключение файла либо из APPPATH (если он там есть), либо из SYSPATH.

Второй вопрос решить легче. Кеширование отключается с помощью свойства Kohana::$caching, которое изначально настраивается через Kohana::init() в bootstrap.php, но доступно к изменению в любое время. Так что можно «обернуть» вызовы Kohana::find_files() в Kohana::$caching = FALSE и Kohana::$caching = TRUE до и после поиска (конечно, надо сперва проверять текущее значение свойства $caching, может кеширование изначально отключено). Соответственно надо иметь специальный метод для обращения к таким вот ресурсам (что-то вроде theme::view($name)?), в который все вызовы упаковать.

Мысли изложил, пока тестирую, что может в итоге получиться. А может я копаю не в ту сторону? Что думаете Вы? :)

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в Пишем CMS.

Теги: , , , , .


Комментарии (13)

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. alweb пишет:

    недавно задавался этим вопросом… и даже создавал тему на форуме коханы… к сожалению пока ничего нового… :(

  2. BIakaVeron пишет:

    Посмотрел вопрос. На самом деле все достаточно просто — есть ведь метод Kohana::modules(), который позволяет как получить список модулей (если вызвать без параметров), так и установить новый перечень модулей для работы.

    Другое дело, что если вызывать данный метод каждый раз при необходимости поиска элемента темы, получим неоднократную обработку этого списка (ведь каждый переданный модуль проверяется на существование, определяется полный путь к нему и т.д.). Поэтому я и хочу работать напрямую с результатом обработки модулей — со свойством Kohana::$_paths.

  3. alweb пишет:

    Я уже портировал свой класс на Ko3. Да, Иван. иметь доступ к $_paths это было бы хорошо. Однако тогда на разработчика перекладывается одна из важнейших задач ядра: управление этим массивом. А он (массив) никак не должен быть перегружен. Например с 100 записями этого массива уже заметно замедление работы самого ядра (kohana::find_file работает заметно медленнее)… Можете протестировать. Однако мне бы хотелось иметь класс управления темами, с функциональностью темизации отдельных страниц, блоков, элементов — всё это «на лету», для различных пользователей и даже для ролей. Этот класс должен содержать функционал на подобие того, что вы упомянули — theme::view($name), theme::render($name) и т.д… Сейчас работаю над ним… Появилась идея портировать такой класс из Drupal. Но обдумав и рассмотрев все внимательно, понял что и это не выход… Но имеет смысл позаимствовать именно функционал (не реализацию).

  4. alweb пишет:

    Кстати, с наступающим Новым Годом ;) Удачи, хороших идей и множество реализованных задач и поставленных целей в Новом Году! :D

  5. BIakaVeron пишет:

    @alweb
    Собственно основная мысль была как раз во временной подмене свойства $_paths на нужный нам массив тем. Так что перегрузку допускать я не хочу. На самом деле если в данном массиве так много записей, то уже возникает вопрос о неправильной работе с модулями. Скорее всего большая часть записей лишняя, надо использовать что-то вроде «ленивой загрузки».

    PS. Спасибо за поздравления, Вас тоже с праздниками. Желаю, чтобы как результаты, так и сам процесс программирования приносили сплошное удовольствие!

  6. aktuba пишет:

    >Скорее всего большая часть записей лишняя, надо использовать что-то вроде “ленивой загрузки”.

    Что это означает? Можно с примером?

  7. BIakaVeron пишет:

    Идея в том, чтобы отсекать неиспользуемые модули, подгружая их в случае необходимости. К сожалению, это в полной мере относится только к своим разработкам. Например, если есть модули Core, Blog, Photo и Forum, имеет смысл заранее в bootstrap.php добавлять только Core, т.к. из трех остальных модулей наверняка будет использован только один. Чтобы его вычислить, скорее всего придется автоматом добавлять все роуты из данных модулей (это задача Core), а потом на основании подходящего роута инклюдить нужный модуль.

    Пока идея на стадии обдумывания, так что конкретный пример не приведу. Конечно, что-то подобное можно придумать и относительно некоторых стандартных модулей (Image, Gravatar и т.д.).

    PS. Насчет сотни записей, Вы скорее всего имели в виду свойство $_files? А то я сперва подумал, как можно сотню модулей наинклюдить :)

  8. aktuba пишет:

    Может имеет смысл пойти другим путем: сделать 2 типа модулей — кешируемые и не кешируемые. Через тот же kohana.php, например. Ведь данные для Blog, Photo и Forum можно закешировать, а вот для Themes уже не стоит.

  9. BIakaVeron пишет:

    Почему не стоит? Просто кэш для тем должен быть вариативным (учитывать текущее имя темы), тут надо подумать над реализацией.

    Но вообще проблема неиспользуемых модулей меня волнует, буду думать дальше.

  10. alweb пишет:

    да… проблема неиспользуемых модулей…
    а точнее проблема ненужных путей ;)
    она конечно выходит за рамки классо/ов Темизации.

    эта проблема пока не актуальна.
    и станет она актуальной когда количество одновременно работающих модулей в CMS достигнет хотя бы 50…
    не секрет, что есть такие CMS/CMF, которые работают с большими нагрузками, одновременно используя при этом огромное количество различных модулей.

    Лично мне кажется, что между понятиями «ленивая загрузка» и «автоматическая загрузка» есть некоторая тайная связь :) .
    Автоматическая загрузка подразумевает то, что при создании объекта, файл с классом должен находиться в тех самых путях, которые содержатся в protected Kohana::$_paths. При этом, если увеличивается количество рабочих модулей, автоматическая загрузка становится действительно «ленивой», т.к. работа ядра существенно замедляется…
    где-то я уже такое видел… :)
    как бы объяснить этой системе какие пути включать, а какие нет… :?:

  11. BIakaVeron пишет:

    Вот поэтому-то я и хочу для тем и плагинов использовать свои пути. Зачем мешать их с действительно «нужными» классами, затруднять поиск файлов и т.д., если достаточно простыми средствами можно выделить им свою песочницу.

    Просто мне кажется, что Kohana не должна знать, что могут быть разные $_paths — это дело для отдельного класса, который должен подменять нужные свойства. По крайней мере я сейчас остановился на таком этапе.

    По поводу ленивой загрузки модулей я задумался не только из-за возможной перегрузки $_paths. Ведь и на инициализацию модулей тратится время. Хотя пока я не располагают большим количеством подключаемых модулей, имеет смысл предусмотреть механизм отсеивания лишнего уже сейчас, так сказать «на вырост» ;)

  12. solarisadmin пишет:

    Спасибо за материал, пригодился. И вообще интересно пишете, подписался на рсс :)
    И еще вопрос, а вы только с kohana работаете?

  13. BIakaVeron пишет:

    @solarisadmin
    На изучение других фреймворков нужно еще время, а его всего 24 часа в сутках ))



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.