Головная боль любого верстальщика - смесь HTML и PHP-кода. Особенно запутанным будет код, в котором используется множество вложенных тэгов, css-классы и стили.
При выводе записей помощью PHP-кода получаются необходимые данные, но для вывода в браузер, нужно его оформить в HTML. Сложность здесь в том, что на уровне PHP невозможно заранее определить какие именно данные потребуются для вывода.
Например - заголовок записи. Если это главная страница, то это должна быть ссылка. Если одиночная, то просто H1. Если это какой-то виджет, то просто текст.
Именно по этой причине в MaxSite CMS с самых первых версий используются универсальные функции mso_page_...() в которых можно указать HTML-оформление. Этот подход на порядок проще, чем заставлять верстальщика оперировать PHP-переменными: код был бы в несколько раз сложней и запутанней (одни if-условия чего стоят...).
Вместе с тем, нельзя не заметить, что в шаблонах часть функций mso_page_... повторяется без изменений в части аргументов. Если это заголовок, то скорее всего это будет тэг H1 в виде ссылки.
Таким образом достаточно давно у меня возникала идея организовать вывод записей в виде некой форматированной строки. Скрипт будет сам её разбирать и подставлять соответствующую mso_page_...-функцию с требуемыми аргументами.
Со временем идея немного трансформировалась в универсальный PHP-класс Page_out, готовый для работы с произвольным HTML-кодом.
Скорее всего верстальщики вздрогнут, поняв, что вывод HTML будет реализован с помощью PHP, но здесь есть один гиганский плюс в том, что результирующий код будет проще и более наглядней, чем «адская» смесь PHP и HTML.
Основная задача php-класса - это вывод записей. Я использую его для формирования главной страницы сайта. Но, технически же нет никакой разницы где он используется.
Покажу на примере простого вывода записей.
В первую очередь необходимо подключить файл и инициализировать его. Файл находится в detault-шаблоне в каталоге stock/page-out. Нужно скопировать его в свой шаблон.
require_once(getinfo('template_dir') . 'stock/page-out/page-out.php'); $p = new Page_out; // сразу подготавливаем объект для вывода записей
Дальше все операции выполняются с $p. Рассмотрим следующий пример вывода трех последних записей:
if ($pages = mso_get_pages(array( 'limit' => 3, 'pagination' => false, ), $temp)) { foreach ($pages as $page) { $p->load($page); // загружаем данные записи $p->line('[title]'); // заголовок $p->line('[date] [cat]', '<p class="info">', '< /p>'); $p->content(); // текст } }
Функция mso_get_pages() получает записи. Первый аргумент - массив параметров, согласно которым происходит выборка записей. Это стандартный код, не будем на нем останавливаться. Второй аргумент - $temp - нужен для пагинации. В этом примере она не используется.
Далее формируется стандартный foreach-цикл вывода записей, но уже основанный на Page_out.
Метод load() загружает текущую запись в объект $p. Метод line() выводит форматированную строчку. Первым параметром указывается строка подстановки, вторым - текст до, третим - после. Уникальность line() в том, что каждый элемент подстановки может обрамляться своим HTML-кодом (или произвольным текстом).
В нашем примере код [title] выводит заголовок записи. Код с «[date] [cat]» выводит дату записи и рубрики в p.info.
Метод content() выводит текст записи.
Пример достаточно простой, но отлично демонстрирует более простой код, чем «стандартный», которым мы обычно и пользуемся в шаблонах (в type-файлах). В качестве возможных подстановок в line() можно использовать:
- title - заголовок записи
- date - дата
- cat - рубрики
- tag - метки
- feed - rss-подписка на комментарии записи
- comments - ссылка на комментарии
- autor - автор
- edit - ссылка на редактирование записи
- read - аля «читать далее»
Каждый их этих кодов имеет свой формат вывода. Например title по-умолчанию выводится как H1. Если же нужно изменить на другое оформление, то просто задаём требуемый формат:
$p->format('title', '<h2>', '</h2>', true); // до, после, формировать ссылку
Задать формат лучше перед циклом foreach.
Каждый код содержит разное количество аргументов и свои дефолтные значения. Приведу format из дефолтных значений:
$p->format('title', '<h1>', '</h1>', true); // до, после, формировать ссылку $p->format('date', 'Y-m-d H:i:s', '', ''); // формат даты, до, после $p->format('cat', ', ', '', ''); // разделитель, до, после $p->format('tag', ', ', '', ''); // разделитель, до, после $p->format('feed', 'Подписаться', '', ''); // титул, до, после $p->format('autor', '', ''); // до, после $p->format('edit', 'Редактировать', '', ''); // титул, до, после $p->format('read', 'Читать дальше', '', ''); // титул, до, после $p->format('comments', 'Обсудить', 'Посмотреть комментарии', '', ''); // без комментариев, есть комментарии, до, после
Понятно, что задавать их нет смысла, они и так используются. Но в данном примере видно где и что менять при необходимости. Например изменим заголовок записи и формат даты:
$p->format('title', '<h4>', '</h4>'); $p->format('date', 'd/m/Y'); foreach ($pages as $page) { $p->load($page); $p->line('[title]'); $p->line('[date] | [autor] | [comments]', '< p>', '< /p>'); ... и т.д.
Эти примеры - основа вывода через Page_out. Вместе с тем, класс содержит методы, которых нет в «стандартных» функциях. Например вывод контента возможен с обрезкой по максимальному количеству слов:
$p->content_words(10);
Или по максимальному количеству символов:
$p->content_chars(100);
Можно вывести произвольное мета-поле, например:
$p->meta('title', 'Титул: ');
Если же нам нужно только получить значение мета-поля, то делаем так:
$meta_title = $p->meta_val('title');
Также доступны любые данные записи. Формально $page - это массив из полей, совпадающих с таблицей базы данных. Например, чтобы получить id записи:
$id = $p->val('page_id');
Точно также можно получить любое другое поле.
Для вывода заголовка можно использовать не только line(), но и специальный метод title(). Удобство в том, что он позволяет сформировать заголовок, без учета заданного в format. Используется, например для формирования UL-списка записей:
$p->title('<li>', '</li>');
Если необходимо получить адрес записи, то используется метод page_url():
$url = $p->page_url();
Для вывода произвольного HTML используется метод html().
$p->html('<hr>');
Более сложный метод block() позволяет организовать вывод данных только если есть какое-то содержимое. Например, если задано мета-поле, то выводим какой-то блок. Если нет, то ничего. Раньше нужно было бы вводить if-условие и проверять содержимое мета-поля. Теперь block() делает это сам. Вот пример с рубриками:
$bl = $p->line_r('[cat]', 'Рубрики: '); $p->block('< p>', '< /p>', $bl);
Кстати метод line_r() полностью аналогичен line() с той разницей, что всегда возвращает данные через return, а не по echo. (Впрочем, это также настраивается.)
Метод div() призван выводить DIV с указанным текстом и css-классом.
$p->div('Текст', 'red');
Сформирует
<div class="red">Текст</div>
Впрочем div() позволяет формировать и произвольный HTML-тэг. Он указывается третьим параметром:
$p->div('Текст', 'red', 'span');
Получится
<span class="red">Текст</span>
В цикле вывода записей можно использовать счетчик. Он бывает полезен, когда требуется «отловить» какую-то конкретную запись, например первую или последнюю. Счетчик перед foreach-циклом следует сбросить, указав общее количество записей.
$p->reset_counter(count($pages)); // сброс счетчика/кол-во записей foreach($pages as $page) { $p->load($page); $num = $p->num; // номер текущей записи ... if ($p->last) $p->html('<hr>'); // последняя запись }
Ещё одной замечательной возможностью Page_out является формирование box - эдакий аналог таблиц, только основанных на DIV'ах. По сути это и есть таблица только с display:table. Скрипт сам формирует требуемые тэги и их css-классы.
Рассмотрим простой пример с однострочной таблицей.
$p->box_start(); // старт $p->cell('111'); // вывод ячейки $p->cell('222'); // вывод ячейки $p->cell('333'); // вывод ячейки $p->box_end(); // конец
LESS/CSS стили будут такими:
div.box { display: table; width: 100%; div.row { display: table-row; div.cell { display: table-cell; } } }
Если необходимо указать дополнительный css-класс, то он указывается первым параметром box_start(). Метод cell() выводит указанный в первом аргументе текст. Вторым аргументом можно указать произвольный css-класс.
Если требуется более сложное формирование строк, то можно их объявить явно.
$p->box_start('css-класс', false); // старт $p->row_start(); // старт строки $p->cell('111', 'css-класс'); // вывод ячейки $p->cell('222'); // вывод ячейки $p->cell('333'); // вывод ячейки $p->row_end(); // конец строки $p->row_start(); // старт строки $p->cell('444', 'css-класс'); // вывод ячейки $p->cell('555'); // вывод ячейки $p->cell('666'); // вывод ячейки $p->row_end(); // конец строки $p->box_end(); // конец
Очень похоже на то как формируется TABLE. Если же в ячейке какой-то сложный вывод, то её можно вывести явно. Вместо cell() используем cell_start() и cell_end():
... $p->cell_start('css-класс'); $p->line('[date]'); $p->content_words(20, '...'); $p->cell_end(); ...
Как мы видим, Page_out значительно упрощает написание кода. Поскольку это новый подход, то он еще будет «оттачиваться» и улучшаться, но его уже можно использовать в своих шаблонах.
Комментариев: 46 RSS
1elle14-08-2012 18:37
Вроде только только наступает момент, когда ты что то (чуть чуть) начинаешь понимать в системе (MScms)...
И тут БАЦ!!!
Новые фишки...
И ты снова НИЧЕГО не понимаешь!:lol:
2Аноним14-08-2012 20:05
Ничего страшного нет. Это хорошо , что задана хорошая динамика в развитии. :-)
На самом деле на "старых" знаниях можно жить достаточно долго. ;-)
3Сергей02-11-2012 09:39
Здравствуйте!
Подскажите, пожалуйста, как сделать файл home.php, чтобы на Главной выводилась статичная запись. Если в админке задать вывод на Главной по номеру записи, то получается дублирование, т.к. один и тот же контент будет и на Главной и в записях /page/запись. Пробовал делать тип страниц "home", но как такую запись вывести на Главную, вот в чем проблема.
4Аноним02-11-2012 09:50
Если я верно понял задачу, то в type_foreach-файле home-top-mso-get-pages.php укажите
5Сергей02-11-2012 10:11
Что-то я делаю не так.. По порядку. В админке Вывод записей -> убраны все отметки, создан тип страниц "home", создана запись с типом "home", в home-top-mso-get-pages.php указан
, но запись "home" на Главную не выводится.6Аноним02-11-2012 10:18
Нужно указать номер top-записи в админке.
7Сергей02-11-2012 10:23
Тогда она будет дублироваться в /page/запись. Как этого избежать, вот в чем задача. Чтобы создал запись с типом, допустим, "home", и она была бы только на Главной.
8Аноним02-11-2012 11:47
Вообще-то это разные страницы. Не нравится, ставьте редирект.
9Сергей02-11-2012 11:51
Значит нет решения по данной задаче? Можно, конечно, в robots запретить индексацию /page/запись, но хотелось как-то через шаблон сделать...
10Сергей02-11-2012 11:54
Страницы-то разные - ДА, согласен. НО контент получается дублированный, что для Главной, наверно, не есть хорошо?
11Аноним02-11-2012 11:58
С какой радости он дублированный? На главной выводятся ещё и другие записи.
В любом случае все записи доступны по отдельной ссылке. Не нравится, ставите редирект, прописываете 404-заголовок для этой записи и т.п.
12Сергей02-11-2012 12:16
Почему ещё другие записи? Речь идет про одну запись на Главной (один уникальный текст, так скажем). А так получается, что в индекс попадает Главная и, та top-запись /page/запись, что выводится на Главной. Соответственно, контент получится дублированным по разным адресам. Разве не так?
13Аноним02-11-2012 12:51
Top-запись - это запись перед другими записями.
14Сергей02-11-2012 13:51
Спасибо, разобрался! Текст для Главной можно вставить в html через "Текст для главной перед всеми записями", а другой Вывод записей убрать. Тогда получится текст на Главной уникальным.
15Аноним12-02-2013 09:07
Привет Макс. Если задавать комменты
И выводить потом, к ним присобачиваются скобки.
Как их убрать?
Я нашел обход, вычисляю количество комментов на странице, и потом вывожу предварительно обернув счетчик комментариев в ссылку.
Но, возможно, есть более рациональный способ?
16Аноним12-02-2013 10:05
Через format — никак. Такова реализация. Если же нужно получить количество комментариев отдельно, то это так:
17Аноним12-02-2013 11:27
Ясно спс.
А на выходе будет ссылка которая ведет на комменты страницы, или просто текст?
18Аноним12-02-2013 11:43
Число — количество комментариев. Используй как угодно.
19Аноним12-02-2013 15:28
Макс еще такой момент.
Если я хочу использовать свой тип страниц, но не хочу, что бы в самих страницах, когда заходишь отображалась шапка, подвал и сайдбар.
Тупо один контент.
Пример,
1. Тип страницы из админки template
2. Создаю каталог в type/template
3. В нем размещаю main.php и издеваюсь как хочу над выводом самой страницы с контентом?
Просто я вроде бы все это проделал, но вроде как не подхватывает :)
По тому ли пути я иду?
20Аноним12-02-2013 15:40
если на шаблоне D2 - то немного не так..
если это главная страница - то type/home/home/my_home.php
в которой у вас и расписана верстка (шапки, подвалы.. или нет их)
а если просто для страниц своего типа - то
и для своего шаблона - делаете по аналогии с указанием type = типу страниц для вывода
Насколько я смог разобраться, то вроде так.
21Аноним12-02-2013 15:45
Если главная страница то - type/home/my_home.php
Но это я указываю вывод всех записей - списка.
А мне надо что бы страницы с типом template, когда заходишь именно в них, отображались без подвала, сайдбара и шапки.
В общем свой вывод надо указать.
22Аноним12-02-2013 16:47
Тип записей и тип данных разные вещи. Поэтому вначале настраивается тип данных, а в этом файле для page смотрится тип страницы и от этого подключаются/отключаются нужные блоки или файлы.
23Аноним12-02-2013 16:55
Это я понимаю, но не совсем догоняю схему реализации.
Я создал тип записей template из админки.
Затем в шаблоне в папке type - создал папку template
Создал файл template.php что бы по адресу http://sait/template/ выводить каталог, в котором бы отображались записи только этого типа.
Все это реализовано и работает. Но вот проблема именно в том - "как поиздеваться над выводом контента самих записей с этим типом" :)
Никак не получается осилить. Дай плиз подсрачника направляющего. Типо:
1. Создай файлик там с таким то именем и укажи в нем условие.
2. А вот в этом файлике укажи усовие такое то.
3. ...
Мне код расписывать не надо. Просто не знаю уже куда рыть.
Спасибо Макс.
24Аноним12-02-2013 17:04
Непонятно. Type-файл template — что выводит? Список записей или тип page? То есть какой тип данных у него?
25Аноним12-02-2013 17:12
Он выводит список записей с типом template.
Я его создавал с одной целью - выводить список записей с одноименным типом заданным из админки - template.
Это я все реализовал, описал сугубо что бы ты видел всю картину.
Мне надо что бы когда заходишь на сами записи (с типом заданным из админки template) - в них не показывались шапка, сайдбар и подвал.
Я приблизительно знаю как это сделать при помощи стилей (поставить условие, что при попадании на страницу с таким типом добавить к body какой нибудь класс, а там дальше display:none в помощь).
Но я хочу понять, как сделать что бы шапка, сайдбар и подвал РЕАЛЬНО не выводились.
А здесь по ходу уже надо работать с типом данных...
26Аноним12-02-2013 17:18
То есть тип данных всё-таки — page.
Для смены main-шаблона для этого типа делаешь main-файл в main/.../main.php и выбираешь его при создании записи.
27Аноним12-02-2013 17:19
По аналогии с no-sidebar.
28Аноним12-02-2013 17:26
Это я уже реализовал. Только что :)
Но мне в плане саморазвития хочется сделать так, что бы ничего указывать кроме типа страницы не надо было.
Сам себе в голову забил короче. В общем в одном месте свербит и все тут :)
Да тип данных именно page. Но как работать с другим типом данных?
29Аноним12-02-2013 17:31
Для page main-шаблон как раз и выбирается при редактировании — в этом и есть её смысл. Если же ты хочешь изменить такое поведение, то используй custom/main-template.php, где по своим условиям выставляешь путь к подключаемому main-файлу.
Для других типов main-шаблон это main/type/ТИП/main.php
30Аноним12-02-2013 17:35
И ещё до кучи добавлю. Если нужно зарегистрировать свой тип данных, например super, то делаешь файл application/controllers/super.php
Теперь в системе на любом уровне можно проверять тип через is_type('super'). То есть работают все плюшки, связанные с типом данных.
31Аноним12-02-2013 17:44
Ясно. Вот уж спасибо!
Вот я так вначале делал по похожему принципу. Только я все делал в файлах шаблона, в папке type, т.е:
Потому и не работало. Надо было получается в шаред каталоге новые файлы создавать.
А не плохо было бы такое реализовать, что бы MaxSite поддерживал.
Т.е. если создаешь в админке тип данных loh, создаешь в шабоне:
Прописываешь то что надо.
И все само собой подхватывалось из этого файла main.php
Не знаю правда насколько это осуществимо.
32Аноним12-02-2013 17:45
Т.е. не тип данных а тип записей.
33Аноним12-02-2013 17:50
Ничего в shared создавать не нужно. Все действия только в своём шаблоне. ;-)
Тип страниц (записей) несёт немного другой смысл. В первую очередь это возможность управлять выводом данных, то есть что-то вроде аля-рубрики. На уровне записей, всё-таки удобней выставлять main-шаблон вручную. Всё-равно нужно указывать тип, тут же указывается и шаблон модульной сетки.
34Аноним12-02-2013 18:11
Весьма полезная вышла дискуссия.
В чем же на самом деле принципиальное отличие каталога main от type ?
Неужели только тем что main можно пристегивать к типу страниц в админке, а type нет? И правильно ли я понял, что type_foreach-файлы - это теперь атавизм от defoult шаблона и в D2 они не используются?
35Аноним12-02-2013 18:58
Бля, я еще больше зауважал твой D2 :)
type_foreach файлы я воспринимаю как мелкие правки к шаблону. Т.е. если в type надо что то глобально фигячить.
То type_foreach позволяет поиздеваться лишь над определенным кусочком.
Ну это мое воспринятие информация по простому. Я обожаю все упрощать :)
36Аноним12-02-2013 19:42
Main-шаблон — это модульная сетка. Type-файл — это вывод контента определенного типа данных. Условно можно считать, что type-файл выводится внутри main-файла. Type_foreach-файл используется внутри type-файла для небольших точечных изменений.
37Аноним12-02-2013 20:13
Вы знаете Максим, я уже не первый день бьюсь на загадкой статьи http://maxsite.org/page/tipy-stranic-v-maxsite-cms
И я лично думаю что понять это у меня не получается из-за того что :
1. Тип страниц мы явно указываем в админке - это ясно.
2. А когда мы собираемся записи этого типа страниц выводить на экран на сайте - то начинаем оперировать типом данных (который мы как бы и не задавали нигде, но фактически подразумеваем, что это данные записей созданных нами типа страниц).
В итоге новичкам вроде меня, немного непонятно, как же все-таки теперь в D2 правильно организовать вывод записей страниц своего типа - в списке, каждой по отдельности.
Как говорится, не дай вам бог жить в эпоху перемен. Учимся на уроках от уже устаревшего шаблона, а пытаемся сделать хоть что-то в D2 :(
38Аноним12-02-2013 20:30
Старые обучалки рассчитаны на default-шаблон и полностью сохранили свою актуальность. В D2 немного другая организация файлов, поэтому и возникают какие-то нюансы. Это неизбежно. Система развивается.
39Аноним12-02-2013 21:30
И это на самом деле очень радует.
Еще бы толкового учителя найти ...
40Аноним13-02-2013 07:04
Да согласен.
Сравнить ту систему, которую я поставил в первый раз :) Еще 0.35 была как помню :) Большей части того, что сейчас небыло, но она уже мне понравилась больше чем WP.
А сейчас я очень рад, что когда то пересел на нее.
41Аноним13-02-2013 07:05
Макс, ты вообще хоть один момент можешь назвать, где WP реально лучше MS?
Ну кроме кол-ва плагинов и шаблонов и обучалок.
42Аноним13-02-2013 08:05
Ну пожалуй только то, что к нему написано больше плагинов и шаблонов. :-) С технической точки зрения WordPress застрял в 2005 и не развивается.
43Аноним13-02-2013 08:19
Максим, может напишите пошаговый урок по теме этого обсуждения?
Скажем делаем свой тип страниц - организуем его вывод на главной, по отдельному пункту в меню - подробным списком, кратким списком (как их можно настраивать), и как выводить отдельную запись из этого списка. Плюс какие лучше плагины использовать для вывода в сайд баре своего типа страниц - и как организовать вывод записи из сайдбара.
Думаю урок будет очень полезен особенно для D2.
Лично от меня - благодарность не будет иметь границ, в пределах разумного :)
Сергей, а вы б все ж таки на своем сайте не оставляли коментарии без ответов. А то я уже потерял надежду увидеть ответ.
С уважением, Вячеслав
44Аноним13-02-2013 09:07
Да не нужны типы страниц для таких вещей. Для группировки записей предназначены рубрики. Типы страниц — это какие-то особые случаи, вроде как static, чтобы исключить вывод в лентах записей.
45Аноним13-02-2013 09:21
Ну пока я не придумал другого способа организовать некое подобие базы данных.
Т.е. типы страниц я использую как аналог таблиц базы. При этом есть ложности со связями их между собой (пока эксперементирую с метаполями, через метки, рубрики, родительская-дочерняя, но пока все выходит коряво, особенно в тот момент когда сущности связываются как многие ко многим).
Как раз и есть особый случай.
Я поначалу думал что есть какой то плагин для всего этого, но кроме http://filimonov.com.ua/page/custom_meta ничего не смог найти.
46Аноним13-02-2013 10:20
Да кстати, я сортирую по типам страниц свой каталог шаблонов.
Но с таким же успехом можно было сортировать это все и по рубрикам.
Просто в условиях задаешь рубрику, страницы которой должны отображаться в каталоге.