Современная, быстрая и удобная система управления сайтом

Форматированный вывод записей в MaxSite CMS

Архив записейКомментарии: 46Просмотров: 6443

Головная боль любого верстальщика - смесь 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 укажите

$par['type'] = false;

5Сергей02-11-2012 10:11

Что-то я делаю не так.. По порядку. В админке Вывод записей -> убраны все отметки, создан тип страниц "home", создана запись с типом "home", в home-top-mso-get-pages.php указан

$par['type'] = false;
, но запись "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

Привет Макс. Если задавать комменты

$p->format('comments', 'Обсудить', 'Посмотреть комментарии', '', '');

И выводить потом, к ним присобачиваются скобки.

Как их убрать?

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

echo '<a href="' . $url . '#comments">' . count($comments) . '</a>';

Но, возможно, есть более рациональный способ?

16Аноним12-02-2013 10:05

Через format — никак. Такова реализация. Если же нужно получить количество комментариев отдельно, то это так:

$p->val('page_count_comments')

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-файлы теперь находятся в shared/type и теперь организованы по своим подкаталогам.

и для своего шаблона - делаете по аналогии с указанием 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 и выбираешь его при создании записи.

28Аноним12-02-2013 17:26

Это я уже реализовал. Только что :)

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

Сам себе в голову забил короче. В общем в одном месте свербит и все тут :)

Да тип данных именно page. Но как работать с другим типом данных?

29Аноним12-02-2013 17:31

Для page main-шаблон как раз и выбирается при редактировании — в этом и есть её смысл. Если же ты хочешь изменить такое поведение, то используй custom/main-template.php, где по своим условиям выставляешь путь к подключаемому main-файлу.

mso_set_val('main_file', 'путь к main-файлу');

Для других типов main-шаблон это main/type/ТИП/main.php

30Аноним12-02-2013 17:35

И ещё до кучи добавлю. Если нужно зарегистрировать свой тип данных, например super, то делаешь файл application/controllers/super.php

<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); 
$this->_view_i('super');

Теперь в системе на любом уровне можно проверять тип через is_type('super'). То есть работают все плюшки, связанные с типом данных.

31Аноним12-02-2013 17:44

Ясно. Вот уж спасибо!

Для других типов main-шаблон это main/type/ТИП/main.php

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

шабон/type/template/main.php

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

А не плохо было бы такое реализовать, что бы MaxSite поддерживал.

Т.е. если создаешь в админке тип данных loh, создаешь в шабоне:

шабон/type/loh/main.php

Прописываешь то что надо.

И все само собой подхватывалось из этого файла main.php

Не знаю правда насколько это осуществимо.

32Аноним12-02-2013 17:45

Т.е. если создаешь в админке тип данных loh

Т.е. не тип данных а тип записей.

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

Да кстати, я сортирую по типам страниц свой каталог шаблонов.

Но с таким же успехом можно было сортировать это все и по рубрикам.

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

Оставьте свой комментарий!

Комментарий будет опубликован после проверки

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)