Сегодня мы наконец-то поговорим о загадочных type-файлах.
Шаблоны Clouds и Mini используют файлы типов данных из дефолтного. Когда вы будете ставить какой-то другой шаблон, то будет хорошо, если в нем также будет отсутствовать свой каталог «type». Это означает, что шаблон в полном объеме поддерживает существующие типы данных.
Type-файл home.php
Начнем свое знакомство с вывода главной страницы. Это файл home.php.
Текущий каталог языка
Строчка
mso_cur_dir_lang('templates');
задает текущий каталог для перевода. Перевод и поддержка языков в MaxSite CMS реализуется с помощью функции t(). Первым параметром функция принимает строчку для перевода, вторым - группу перевода. Если вы знакомы с WordPress, то знаете, что в нем используется единый файл перевода, который грузится всегда в момент старта. Сам перевод имеет довольно большой размер, но вся «прелесть» заключается в том, что в нем львинная доля - это перевод админ-панели. Совершенно очевидно, что для простого посетителя все они не нужны в принципе, но при этом создают лишнюю нагрузку на сервер.
Возможно вы пользуетесь сборкой WordPress, где используется разделение файла перевода на полную и lite. Я придумал этот алгоритм к версии 2.3 и насколько знаю, он в неизменном виде и сейчас существует в разных «самостоятельных» сборках WordPress.
Так вот. Разработчики WordPress давно уже плюнули на внутреннюю оптимизацию своего детища, поэтому для них лишние 2-3Мб потребляемой памяти не играют существенной роли. Но, не для меня. Поэтому в MaxSite CMS принято, что строка для перевода будет находится в какой-то своей группе. Например есть группа «templates» - это перевод фраз, встречающихся в шаблонах. «Admin» - перевод админ-панели. «Plugins» - перевод плагинов.
Кроме этого в t() можно указать «__FILE__», которое будет интерпретированно как свой собственный каталог с файлами перевода. Посмотрите для примера плагин «Admin_announce» - в нем отдельный каталог «language», в котором и находятся файлы с переводом.
Что же касается самого файла перевода, то это самый обычный php-файл, где фразы оформляются в виде массива $lang.
Таким образом в MaxSite CMS очень просто создать, редактировать и менять языковые файлы. Кроме того, можно выставить отдельные языки для разных частей сайта. Например админку сделать русской, а сам сайт - украинским.
Теперь вернемся к mso_cur_dir_lang(). Данная функция предназначена для того, чтобы быстро задать группу перевода. В нашем случае это будет templates и во всех последующих вызовах t() можно опустить второй параметр. Это несколько упрощает результирующий код и делает его более читабельным.
Разный вывод
Строчка
if (mso_get_option('home_cat_block', 'templates', '0'))
подключает файл home-cat-block.php в случае, если установлена опция home_cat_block. Эта опция называется «Блоки рубрик на главной» (в настройках шаблона). Для вывода блоков используется более сложный алгоритм и делать его в одном файле я посчитал неразумным.
Страница перед всеми записями
Далее мы смотрим опцию home_page_id_top и если она отмечена, то получаем эту самую страницу. Тут мы впервые сталкиваемся с функцией mso_get_pages(). Это одна из самых мощных и универсальных функций, поскольку именно она избавляет нас от составления сложных SQL-запросов и сразу преподносит нужные записи в удобном для вывода формате.
Для того, чтобы указать mso_get_pages() какие именно записи нам нужны, в первом параметре задаем массив опций. Второй параметр нужен для формирования пагинации - листалки страниц (он встретится ниже).
Для удобства параметры для получения страниц я вынес в переменную $par. Давайте кратко остановимся не некоторых наиболее важных.
Некоторые параметры для mso_get_pages()
Ниже список в таком формате: «параметр (значение по умолчанию) - описание».
- limit (7) - количество записей на одной странице.
- page_id (0) - номер страницы, которую нужно получить. В нашем случае этот номер определен в опции «home_page_id_top».
- cut (Далее) - текст для ссылки на продолжении текста. Если нужно вообще отключить деление записи, то есть вывести её целиком, то нужно указать: 'cut' => false.
- cat_order (category_name) - поле по которому сортируются рубрики записи. Когда у вас отмечено несколько рубрик у записи, можно указать в каком порядке они будут отображаться.
- cat_order_asc (asc) - прямой или обратный порядок отображения рубрик записи.
- pagination (true) - следует ли формировать данные для пагинации. Если нам нужно вывести одну страницу, то очевидно, что пагинация нам не нужна. Отключение пагинации экономит один запрос к БД.
- cat_id (0) - номера рубрик из которых выводить записи. Например мы хотим выводить на главной только рубрики «Новости» и «О важном». Указываем их через запятую.
- content (true) - нужно ли получать весь текст из базы. Очень часто бывают ситуации, когда нам не нужно получать текст, а только заголовок записи или какие-то другие данные. Тексты обычно большие по размеру, поэтому на них тратится больше php-памяти. Вот для таких случаев и ставим этот параметр в false.
- type (blog) - какой тип страниц (не типов данных!) выводить. По-умолчанию мы выводим на главной только страницы типа «blog», а другие не выводятся. Тип страниц - это дополнительная группировка, что-то вроде рубрик, только в более глобальном варианте. Если вам нужно задать несколько типов одновременно, то их следует оформлять в виде массива: 'type' => array('static', 'help', 'lections').
Думаю, что уже этих знаний вам будет достаточно, чтобы понять как настроить вывод любых вариантов.
Вот кстати, в WordPress'е мы обычно называем «страницей» - «постоянную страницу» - тип «static», а для типа «post» используется слово «запись». В MaxSite CMS это лишено смысла, поэтому я использую «запись» и «страница» в обычном понимании этих слов.
Полученный результат для верхней записи сохраняется в переменной $page_top. Если функция mso_get_pages() не смогла получить ни одной страницы, то она возвращает пустой массив.
Получаем основные страницы для вывода
Тут опять же задаем нужные параметры для mso_get_pages() и получаем массив страниц.
Посыл header, если страниц нет
Строчка с header() отправляет http-заголовок браузеру в случае, если не найдено страниц.
Подключение main-start.php
Теперь, когда мы получили все данные, мы можем подключить первую часть шаблона: main-start.php. Обратите внимание, как задается путь к этому файлу: через getinfo('template_dir'). Сделано это для того, чтобы наш type-файл мог работать с любым текущим шаблоном.
Непосредственно вывод данных
Дальше вы видите формирование html-тэгов под разные блоки. Для примера рассмотрим строчку:
echo NR . '<div class="type type_home">' . NR;
Константа NR - это символ переноса строки. Используется исключительно для читабельности генерируемого кода. Когда вы будете заниматься отладкой, то скорее всего будете расставлять переносы, чтобы было проще разобраться с результатом.
Классы (class) указаны через пробел. Эта возможность CSS позволяет обращаться к блоку (в данном случае div) двумя способами:
div.type {} div.type_home {}
То есть вначале можно задать общий стиль для div.type, а потом подстроить для своих нужд в виде div.type_home. В MaxSite CMS очень часто встречается подобный подход, поэтому я так подробно на нем остановился.
Цикл вывода
Если вы занимались WordPress, то должны знать, что вывод данных оформляются в виде т.н. цикла TheLoop. Технически это несколько функций, которые последовательно перебирают записи. Меня всегда удивляло такое решение граничащее с глупостью, потому что делать функции для вывода обычного цикла, по меньшей мере странное решение.
Наша функция mso_get_pages() возвращает данные в виде обычного массива и в PHP есть очень удобная функция для организации цикла перебора элементов массива foreach. Поэтому в MaxSite CMS ничего не придумывается, а просто используется то, что и так нормально работает.
Рассмотрим учебный пример такого цикла:
$массив = array('первый', 'второй', 'третий'); foreach ($массив as $элемент) { echo $элемент . '<br>'; }
Данный пример демонстрирует перебор элементов с помощью foreach(). Примерно так же мы и будем выводить записи, только наши массивы немного сложней - они многомерные (массив в массиве).
Цикл вывода
Рассмотрим подробней цикл, поскольку на таком принципе построенны почти все type-файлы.
foreach ($page_top as $page) { extract($page); mso_page_title($page_slug, $page_title, '<h1>', '</h1>', true); echo '<div class="page_content">'; mso_page_content($page_content); mso_page_content_end(); echo '<div class="break"></div>'; echo '</div>'; }
Строчка extract($page); преобразует элементы массива в обычные переменные. Еще один учебный пример:
$массив = array( array('a' => 1, 'b' => 2, 'c' => 3), array('a' => 11, 'b' => 22, 'c' => 33), array('a' => 111, 'b' => 222, 'c' => 323) ); foreach ($массив as $элемент) { extract($элемент); echo $a . ' - '; echo $b . ' - '; echo $c . '<br>'; }
Обратите внимание, что мы нигде не задавали переменные $a, $b и $c. Но зато мы экстрактнули (о!) $элемент и переменные автоматом создались на основе ключей массива.
Все примеры рабочие.
В нашем же цикле автоматом появятся переменные из массива «$page»: $page_slug, $page_title, $page_content и другие.
Если по какой-то неведомой причине вас не устраивает extract(), то получить нужные данные можно так (соответственно): $page['page_slug'], $page['page_title'] и $page['page_content']. То есть обычные ключи массива.
Переменная $page в MaxSite CMS объявлена как глобальная. Сделано это для того, чтобы в цикле вывода сторонние функции, например плагины, могли получить данные текущей записи. Именно поэтому в своих разработках никогда не используйте свою $page.
Функция mso_page_foreach()
Вы заметили, что я опустил разбор функции mso_page_foreach(). К ней мы вернемся немного позже.
Функции вывода записей
Для того, чтобы вывести данные записи в MaxSite CMS предусмотрены функции-обертки, которые несколько упрощают форматирование конечного кода. Можно например, просто вывести $page_content через echo, но тогда потеряются все хуки, по которым может меняться текст.
Ниже я привожу список функций, как они объявлены в MaxSite CMS. Если какой-то параметр не указывается, то берётся значение по-умолчанию (он указан через знак равно). Назначение каждого параметра понятно из его имени.
Формирование загловка/ссылки на страницу.
mso_page_title( $page_slug = '', $page_title = 'no title', $do = '<h1>', $posle = '</h1>', $link = true, $echo = true, $type = 'page')
Вывод текста.
mso_page_content( $page_content = '', $use_password = true, $message = 'Данная запись защищена паролем.')
Функция, которая выполняется после вывода текста. Например некоторые плагины могут здесь выводить какие-то свои данные.
mso_page_content_end()
Вывод даты. Второй параметр ($format) может быть массивом опций: format - формат даты, days - названия дней недели, month - названия месяцев.
mso_page_date( $date = 0, $format = 'Y-m-d H:i:s', $do = '', $posle = '', $echo = true)
Вывод рубрик записи.
mso_page_cat_link( $cat = array(), $sep = ', ', $do = '', $posle = '', $echo = true, $type = 'category', $link = true)
Вывод списка меток записи.
mso_page_tag_link( $tags = array(), $sep = ', ', $do = '', $posle = '', $echo = true, $type = 'tag', $link = true)
Ссылка на редактирование страницы. Отображается у админа и автора записи.
mso_page_edit_link( $id = 0, $title = 'Редактировать', $do = '', $posle = '', $echo = true)
Формирование ссылки «обсудить» если разрешен комментарий. Первый параметр можно задать массивом и в нем уже указать нужные значения. Пример такого использования как раз и приведен в файле home.php.
mso_page_comments_link( $page_comment_allow = true, $page_slug = '', $title = 'Обсудить', $do = '', $posle = '', $echo = true, $type = 'page')
Все эти функции позволяют упростить формирование html в шаблонах и сразу учитывают некоторые особенности и условия.
Полные записи или заголовки?
В цикле вывода вы увидите опцию home_full_text. Если она определена, то выполняется вывод записей в виде последовательных div-блоков. Если же home_full_text = false, то мы выводим только заголовки записей в виде списка ul-li.
Собственно я не вижу смысла останавливаться на каждом варианте, потому что все используемые функции мы уже рассмотрели.
Пагинация
Наш второй параметр в mso_get_pages() создает массив, который нужен для плагинов пагинации. В нем соджержится информация об общем количестве записей, записей на одной странице и т.п. Поэтому строчка
mso_hook('pagination', $pagination);
и выводит пагинацию. В хук pagination мы передаем наш массив. Сам вывод пагинации - это удел плагинов, поэтому мы не будем их рассматривать. Отмечу лишь, что в MaxSite CMS плагинаций может быть много. Например можно их выстроить одну под другой. :)
Если страниц нет
Если вы пользуетесь Notepad2, то для вас не составит сложностей визуально отслеживать блоки {...}. Посмотрим блок else, когда страниц не найдено. В этом случае мы выводим сообщение, что ничего не найдено и выполняем хук page_404. По нему, например будет выводиться архив сайта.
Концовка
Завершает наш type-файл подключение main-end.php.
Вернемся к mso_page_foreach
Давайте теперь поговорим о mso_page_foreach(). Это специальная функция, которая позволяет произвольно настраивать вывод записей в конкретном шаблоне. Делается это через type_foreach-файлы.
Вы наверное заметили, что порядок вывода данных записей жестко задан в type-файлах. Вполне возможны ситуации, когда нужно поменять формат и порядок вывода этих данных. Например нужно убрать вывод меток и дату выводить перед заголовком. Раньше единственным способом решить эту задачу - было полная переписка type-файла в своем шаблоне.
Конечно же это неудобно и прежде всего из-за того, что дефолтные type-файлы могут меняться и нужно возвращаться к своим шаблонам, чтобы привести их в соответствие дефолтными.
Как показывает практика, основные изменения в шаблонах заключаются только в цикле вывода. Таким образом в MaxSite CMS можно задать определенный type_foreach-файл и система, вместо того, чтобы выводить данные цикла по-умолчанию, передаст управление в файл шаблона.
Рассмотрим практический пример. В нашем type-файле:
if ($f = mso_page_foreach('home-top')) { require($f); // подключаем кастомный вывод continue; // следующая итерация }
В функции mso_page_foreach() указывается type_foreach-файл. В нашем случае это home-top. Система проверит наличие файла шаблон/type_foreach/home-top.php и если он есть, подключит его с помощью обычного require() и сразу перейдет к следующему циклу (continue).
Таким образом, механизм type_foreach позволяет легально кастомизировать произвольный шаблон.
Заготовки для type_foreach-файлов находятся в каталоге default/type_foreach. Обратите внимание, что они все начинаются с символа «_». Когда вы будете их копировать в свой шаблон, этот символ нужно удалить. Система автоматически проверит существование всех файлов и будет их подключать по мере необходимости.
Когда мы начинали делать type_foreach, то предполагалось, что будут подключаться файлы только в самом цикле. Но последние изменения в MaxSite CMS позволяют подключать их в произвольном месте type-файла и тем самым предоставляют в ваше распоряжение удобный механизм настройки шаблона под разные задачи.
Функции отладки
Я не предаставляю себе программирование без отладки. В сложном коде порой очень сложно понять где «затык» и нужен способ для его быстрого поиска. Иногда бывают задачи, когда нужно вспомнить структуру массива или посмотреть в каком виде генерируется код. Для всех этих случаев в MaxSite CMS есть несколько функций.
Функция pr()
Функция объявлена так:
pr($var, $html = false, $echo = true)
В первом параметре указываем интересующую нас переменную. Второй позволяет конвертировать чистый html в спецсимволы, чтобы увидеть результирующий код в браузере (правда это работает только для строк). Третий - выводить ли резуальтат в браузер или вернуть по return.
К особенностям pr() относится то, что она умеет работать с любыми входящими типами переменных. Если это строка или число, то выводится обычная строка. Если это массив или объект, то выполняется форматирование, чтобы вы видели структуру.
Дополнительно вывод pr() обрамляется в тэг pre, тем самым в браузере он отображается моноширинным шрифтом.
Когда вам нужно понять как и что устроенно, то вы используете pr(). Например после получения страниц напишите
pr($pages);
и вы увидите массив всех полученных записей. С помощью этой функции вы можете узнать какие данные возвращает mso_get_pages().
Функция _pr()
Эта функция аналогична pr() с той разницей, что после вывода переменной она аварийно завершает выполнение скрипта. Это удобно использовать в случаях редиректов или когда количество последующего вывода велико, а вам нужна только отладочная информация.
Функция _sql()
Данная функция пригодится тем, кто составляет свои запросы к БД. Обычно мы используем Active Records, но иногда нужно контролировать генерируемый SQL. В этих случаях можно принудительно заставить CodeIgniter сформировать запрос и получить его в виде текста. Обратите внимание, что сама функция ничего не выводит, а только возвращает текст текущего запроса по return. Поэтому если вам нужно увидеть запрос, то нужно пользоваться так:
pr(_sql());
В некоторых задачах Active Records не может корректно (или как нам нужно) сформировать SQL-запрос. Можно было бы конечно тогда отказаться от него, но можно просто получить текущий по _sql(), внести необходимые изменения в его текст и выполнить обычным $CI->db->query().
Прочие type-файлы
Я не стану сейчас рассматривать остальные type-файлы, поскольку они практически идентичны нашему home.php с той разницей, что используются другие опции, type_foreach-файлы и немного другой вывод. Постарайтесь хотя бы бегло пройтись по ним, чтобы держать в голове их назначение.
Некоторые type-файлы, например файлы users более сложны, потому что используются не для вывода записей, а для организации страниц комюзеров. Если вы понимаете заключенный в них код, значит для вас открыта дорога к построению на базе своего шаблона небольшой социальной сети.
Чуть позже мы рассмотрим все эти вопросы.
Комментариев: 6 RSS
1Аноним07-01-2010 19:00
Чую, это не последняя статья! Спасибо, Макс, очень нужный цикл.
2leventov07-01-2010 20:11
Осталось поставить ссылку на цикл в админке :)
3Zidar11-02-2011 04:22
Макс, я хочу сделать кино сайт, у меня tags(метки) это актеры. Как мне сделать ещё одни метки для режисеров и использовать функцию типо mso_page_tag_link для них.
kinosite.ru/tags/Джеймс+Камерон - выводятся записи с этим актером.
Как сделать что бы
1) kinosite.ru/director/Джеймс+Камерон - выводились все записи данного режисера
4Аноним11-02-2011 12:53
Ну скопировать в свой шаблон type/tag.php под именем director.php, где в праметрах получения страниц ($par) указать тип custom_type = tag.
5Сергей18-12-2015 10:36
Не могу ни где найти информацию, как на главной странице в анонсах и полной статье сделать вывод автора статьи, в том числе и admin то есть меня? Подскажи пожалуйста.
6Аноним18-12-2015 17:43
См. info-top-файлы