Создание MVC модуля для Joomla 1.5!
И так, «what this MVC?» — это архитектура программного обеспечения, в которой модель данных, пользовательский интерфейс и управляющая логика разделены на три отдельных компонента, и при модификации в каждом отдельном компоненте изменения оказывают минимальное влияние на остальные компоненты. Это одна из важных преимуществ использования MVC в программировании.
Шаблон MVC позволяет разделить данные, представление и обработку на три отдельных компонента 1)Модель (Model). Модель предоставляет данные (обычно для View), а также реагирует на запросы (обычно от контроллера). 3)Поведение (Controller). Интерпретирует данные, введенные пользователем, и сообщает модели и представление о необходимости выполнения определенных действий. 2)Представление (View). Отвечает за отображение информации (пользовательский интерфейс, шаблон вывода данных).
Так выглядит простейшая схема MVC:
Хватит теории, по этом вопросу в сети полно материала, переходим к написанию модуля. И как обычно для начала определимся что будет выполнять наш модуль а далее реализуем это в коде)). А выполнять модуль будет такую полезную вещь как вывод превью статей с кратким описанием из интротекста, превью и заголовок будет ссылкой которая будет вести пользователя на страницу с материалом (статью).
Ко всему этому модуль настраивается из админки, и в его настройках можно указать из какого раздела/категории использовать материалы для отображения. Тоесть должна быть возможность указать на вывод материалов из категории определенного раздела, из раздела по всем категориям этого раздела или же отказаться от разделов и категорий и выводить просто последние N-количество статей, которые опубликованы администратором. Ну и конечно же должна быть возможность указания количества выводимых материалов.
И еще чуть не забыл... Реализуем подключение стилевого файла модуля в Head документа.
И так наш моду будет иметь тематическое название — mod_mvc, и содержать в себе такую структуру файлов и каталогов:
Эта структура на картинке показана не просто так, ее необходимо описать в установочном файле модуля «mod_mvc.xml» для того что бы установщик Joomla содал такую же структуру каталогов в директории /modules, и скопировал в все файлы модуля в соответствующие каталоги данной структуры.
Установочный файл «mod_mvc.xml»:
< ?xml version="1.0" encoding="utf-8"?>
<install type="module" version="1.5.0">
<name>MVC</name>
<author>Cleverscript</author>
<creationdate>December 2009</creationdate>
<copyright></copyright>
<license>GPL 2.0</license>
<authoremail>toorr2p[dog]bigmir.net</authoremail>
<authorurl>http://cleverscript.ru/</authorurl>
<version>0.0.1</version>
<description>Module MVC</description>
<files>
<filename module="mod_mvc">mod_mvc.php</filename>
<filename>helper.php</filename>
<filename>index.html</filename>
<filename>tmpl/default.php</filename>
<filename>tmpl/index.html</filename>
<filename>tmpl/css/index.html</filename>
<filename>tmpl/css/style.css</filename>
</files>
<params>
<param name="moduleclass_sfx" type="text" default="" label="Module Class Suffix" description="PARAMMODULECLASSSUFFIX" />
<param name="source_sec" type="section" default="" label="Раздел" description="Укажите желаемый раздел для вывода превью" />
<param name="source_cat" type="category" default="" label="Категория" description="Укажите желаемую категорию раздела для вывода превью" />
<param name="show_all" type="radio" default="0" label="Без раздела и категории" description="Вывод материалов без учета раздела и категориии">
<option value="0">Нет</option>
<option value="1">Да</option>
</param>
<param name="count" type="text" default="10" label="Количество" description="Укажите желаемое количество выводимых материалов" />
<param name="template" type="filelist" default="default.php" directory="/modules/mod_mvc/tmpl" filter="\.php$" hide_none="1" hide_default="1" label="Шаблон" description="Выберите шаблон модуля" />
</params>
</install>
Начну с описания параметров группы Files (те то перечислены между тегами ) — это и есть наша структура которую будет формировать установщик Joomla при инсталляции модуля, здесь в строгом порядки указываем все файлы ходящие в наш модуль. Первый параметр немного отличается от остальных и имеет такой вид:
<filename module="mod_mvc">mod_mvc.php</filename>
Это файл-входной точки модуля, то есть наш как-бы наш контроллер который запускается Фреймверком Joomla и далее передает параметры в helper.php который использует их для выборки записей из БД и возвращает данные, это будет описано ниже... А так, на что здесь следует обратить внимание это на атрибут module="" в котором должно содержатся имя модуля, которое в свою очередь соответствует названию файла-входа в модуль («контроллера»). Исходя из этого установщик Joomla создаст каталог для модуля с названием из параметра module.
Ну а далее обычным образом перечисляем все файлы и директории модуля, уже относительно папки самого модуля (см. иллюстрацию выше).
Файлы модуля описаны, теперь самое интересное, опишем параметры которые будут доступны в настройках модуля из адми-панели, это те которые в группе «params» (заключены между тегами ).
Первый параметр стандартный — он позволяет указать суффикс класса для выводимого модуля, для применения к нему специфических CSS стилей.
<param name="moduleclass_sfx" type="text" default="" label="Module Class Suffix" description="PARAMMODULECLASSSUFFIX" />
Содержит атрибуты:
1) name — имя параметра; 2) type — тип (тип поля); 3) default — значение поля по умолчанию; 4) label — ярлык возле поля; 5) description — подсказка-описание для поля
Таким образом создается параметр для модуля, значение которого будет доступно в коде модуля и в зависимости от его значения можно выполнять те или иные действия. при этом данное значение хранится в БД Joomla в таблице «dim_modules» в поле «params», для нашего модуля.
Следующие два параметра «source_sec» и «source_cat» имеют другой тип (атрибут type), первый из них отображает выпадающий список всех разделов сайта, а второй категорий по этим разделам, и в своих значениях содержит id раздела и категории — соответственно. С помощью этих двух типов полей администратор может выбрать какой материал выводить.
Третий параметр «show_all» имеет тип radio и содержит для выбора два значения 0 и 1 где ноль это «Нет» а 1 это «Да», по дефолту (default) устанавливается значение 0 — «Нет».
Четвертый параметр «count» — в нем администратор будет указывать какое количество записей отображать.
Ну и наконец то пятый параметр «template» — позволяет выбрать один из нескольких возможных шаблонов вывода материалов, обратите внимание на атрибут «directory» и «filter» первый указывает на папку c шаблонами модуля, а второй на расширение в названии используемых файлов в качестве шаблона.
Ну вот все параметры описаны и теперь после установки модуля в его административной части будет такая картина:
Двигаемся далее, и подходим к описанию принципа работы модуля по шаблону MVC. Запуск модуля, фреймверком Joomla осуществляется таким образом (упрощенное описание) — вызывается файл модуля, в нашем случае это файл mod_mvc.php в котором доступны все значения из полей формы в админке модуля, другими словами доступны параметры в виде пара-значение.
Значение параметра получаем таким образом:
$source_sec = $params->get('source_sec');
Таким образом например, мы получим значение ID раздела, указанного в настройках модуля. Теперь по порядку... Файл модуля mod_mvc.php — это «входная точка» нашего модуля, при его запуске вызывается метод (функция) из helper.php которой передаются параметры о которых я говорил чуть выше, этот метод выполняет определенные операции (выбр из БД, обработка данных и их преобразование и т.д) возвращает данные которые будут выводится через шаблон модуля.
В упрощенном виде это звучит так:
1)Вызов функции с передачей ей параметров и получение данных возвращаемых этой функцией. 3)Подключаем в HEAD стили CSS модуля. 2)Подключение шаблона. 3)Вывод данных в шаблоне.
В файле mod_mvc.php это выглядит так:
< ?php defined('_JEXEC') or die('Restricted access'); //параметры доступные модулю //print_r($params); //Получаем паремтр с именем шаблона $tmpl = str_replace('.php', '', $params->def('template', 'default.php')); //Подключаем наш helper и //и обращаемся к его классу, вызывая метод - который возвращает нам массив обьектов //при этом передавая методу все параметры полученные модулем (из админки) require_once (dirname(__FILE__).DS.'helper.php'); $list = MVC::getList($params); if (!count($list)) { return; } //Подключаем CSS jimport('joomla.document.html.html'); $document =& JFactory::getDocument(); $link = JURI::root().'modules/mod_mvc/tmpl/css/style.css'; $attribs = array('type' => 'text/css'); $document->addHeadLink(JRoute::_($link), 'stylesheet', 'rel', $attribs); //Подключаем шаблон (который указан из админке) $template = JModuleHelper::getLayoutPath('mod_mvc', $tmpl); if (file_exists($template)) { require($template); } else { echo JText::_('ERROR_TEMPLATE'); } ?>
Далее поговорим о helper.php который является по сути «моделью» для получения данных, этот файл содержит в себе один класс — «MVC» который содержит метод (это он вызывается как было описано выше) «getList ()» который принимает параметры, и использует их в своей работе.
Эта функция выполняет запрос к БД и выполняет выборку записей (статей) на основе полученных параметров (настроек из админки модуля).
И так как выглядит этот класс с принадлежащим ему методом, для начала приведу пример того каким образом принимаются параметры (настройки из админки).
Выглядит это так:
class MVC { function getList(&$params) { $db =& JFactory::getDBO(); $source_sec = $params->get('source_sec'); $source_cat = $params->get('source_cat'); $show_all = $params->get('show_all'); $count = $params->get('count'); } }
Здесь получаем соединение с БД JFactory::getDBO () и присваиваем значения параметров переменным. $params — это объект (экземпляр класс stdClass), который является удобным контейнером для передачи данных, в данном случае параметров, print_r ($params) выведет на экран такое:
JParameter Object ( [_raw] => source_sec=9 source_cat=35 template=default.php count= [_xml] => [_elements] => Array ( ) [_elementPath] => Array ( [0] => W:\home\localhost\www\funky_dyk\libraries\joomla\html\parameter\element ) [_defaultNameSpace] => _default [_registry] => Array ( [_default] => Array ( [data] => stdClass Object ( [source_sec] => 9 [source_cat] => 35 [template] => default.php [count] => ) ) ) [_errors] => Array ( ) )
Присвоив переменным значения параметров используем их для формирования запроса к Базе Данных Joomla. А конкретней — в случае если пользователь в настройках модуля указал раздел и категорию и не выбрал опцию «Показывать без учета раздел / категория», а также указал количество выводимых записей (если не указано то 10) формируем запрос следующим образом:
1)Условие в запросе:
if($show_all == 0){ $where = 'sectionid='.$source_sec.' AND catid='.$source_cat.' AND '; }else{ $where = ''; }
2)Сам запрос:
$query = 'SELECT a.*, s.title as stitle, c.title as ctitle, u.name, ' .
' CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END as slug,'.
' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(":", c.id, c.alias) ELSE c.id END as catslug'.
' FROM #__content AS a' .
' LEFT JOIN #__users AS u ON u.id = a.created_by' .
' INNER JOIN #__categories AS c ON c.id = a.catid' .
' INNER JOIN #__sections AS s ON s.id = a.sectionid' .
' WHERE '.$where.
' s.published = 1' .
' AND c.published = 1' .
' ORDER BY id DESC';
Данный запрос выведет только те записи, которые опубликованы администратором.
Выполняем запрос. Если лимит не указан пользователем то выводим все
if($count == ''){ $db->setQuery($query); }else{ $db->setQuery($query, 0, $count); }
Загружаем результаты запроса к БД в массив
$rows = $db->loadObjectList();
А теперь самое интересное, из полученных данных, которые содержатся в виде объекта stdClass, формируем контент с помощью итерации, помещая данные(переменные) в массив в виде ключ=>значение:
$i=0; $lists = array(); foreach ($rows as $row) { //формируем ссылку $lists[$i]->link = JRoute::_(ContentHelperRoute::getArticleRoute($row->slug, $row->catslug, $row->sectionid)); //формируем превью $text = strtolower($row->introtext.$row->fulltext); $regex = "/<img [^/>]+src\s*=\s*[\"']\/?([^\"']+)[\"'][^>]*\>/";//поиск картинки preg_match ($regex, $text, $matches); $images = (count($matches)) ? $matches : array(); if ($images) { $lists[$i]->image = '<img src="'.$images[1].'" alt="thumbs" class="thumbs" />'; $lists[$i]->image = '<a href="'. $lists[$i]->link .'">'.$lists[$i]->image.'</a>'; } //формируем интротекст $lists[$i]->introtext = strip_tags($row->introtext); $lists[$i]->paramss = $params; $i++; }
В начале формируем URL который будет указывать на материал и использоваться в ссылке «Далее» в шаблоне модуля, для этого в самом начале файла нужно было добавить подгрузку файла route.php, в котором содержится класс ContentHelperRoute и вызываемый нами метод getArticleRoute которому в качестве аргументов передаются параметры статьи — id материала с псевдонимом(через двоеточие), id категории и id раздела. При этом формируется ссылка на материал и заносится в элемент массива с ключом «link»:
$lists[$i]->link = JRoute::_(ContentHelperRoute::getArticleRoute($row->slug, $row->catslug, $row->sectionid));
Далее формируем превью (изображение к статье), для этого приводим весь интро-текст и фулл-текст к нижнему регистру и используем поиск тега IMG сразу и в introtext и в fulltext.
Первый найденный тег IMG (или из интро-текста или фул-текста), будет использоваться в качестве превью, вернее из этого тега будет извлечен параметр SRC содержащий путь к картинке, и далее использован в формировании картинки:
//формируем превью $text = strtolower($row->introtext.$row->fulltext); $regex = "/<img [^/>]+src\s*=\s*[\"']\/?([^\"']+)[\"'][^>]*\>/";//поиск картинки preg_match ($regex, $text, $matches); $images = (count($matches)) ? $matches : array(); if ($images) { $lists[$i]->image = '<img src="'.$images[1].'" alt="thumbs" class="thumbs" />'; $lists[$i]->image = '<a href="'. $lists[$i]->link .'">'.$lists[$i]->image.'</a>'; }
К тому же эта картинка еще и является ссылкой на материал.
Следующий этап — формирование интротекста:
//формируем интротекст $lists[$i]->introtext = strip_tags($row->introtext);
При этом с помощью функции strip_tags () удаляем все теги, оставляя только текст.
Сформировав массив с данными возвращаем его в качестве результата работы функции:
function getList(&$params) { ... //возвращаем многомерный массив объектов return $lists; }
Теперь поговорим о шаблоне, файле default.php который находится в папке tmpl. Этот файл подгружается ниже вызова функции getList () в нашем главном файле-входной точки модуля mod_mvc.php (см. выше), и поэтому в нем доступен результат вызова функции.
Так как этим результатом является многомерный массив то в шаблоне обрабатываем его соответствующим образом:
< ?php defined('_JEXEC') or die('Restricted access'); echo "<ul class='mod_mvc'>"; foreach ($list as $item){ echo '<li>'; if (!empty($item->image)) : echo $item->image; endif; echo "<p>".$item->introtext."</p>"; echo "<a href='".$item->link."'>Далее</a>"; echo '</li>'; } echo ""; ?>
Здесь с помощью итерации извлекаем данные из массива и помещаем их в нужные вам контейнеры, для наглядности я решил использовать не маркированный список UL, в котором каждый LI это отдельное краткое описание статьи с превью и ссылкой «Далее».
А оформление CSS прописывается в файле style.css который находится в папке css шаблона модуля, и подключается в документ из файла модуля mod_mvc.php, перед подгрузкой шаблона модуля (см. выше).
В данном примере он содержит описание для элементов списка:
ul.mod_mvc li{width:100%;height:160px;}
Структуру шаблона вы можете изменять по своему усмотрению или же просто создать еще один шаблон и положить его в папку tmpl, а затем указать ваш шаблон из админки.