ВВЕДЕНИЕ
В этой статье я хотел бы рассказать о создании модуля вопросов и ответов для Joomla. В интернете очень много различных примеров, в том числе и в официальной документации, но как правило для новичков бывает сложно самостоятельно разобраться в том или ином примере. Поэтому чем больше существует материалов по данной тематике - тем проще сравнить их между собой, понять принципы, логику и так далее.
В частности в этой статье мы рассмотрим создание модуля вопросов и ответов. Я искал в интернете, нашел кучу статей о создании модулей в принципе, но ни одного, который бы подходил под мои нужды. Поэтому было принято решение написать об этом статью.
Используемые навыки: html, css, bootstrap v4, php, xml, joomla
Что вы узнаете:
- Файловая структура модуля Joomla
- Использование поля subform
- Принципы и порядок создания модулей
Создание модуля F.A.Q. для CMS Joomla
Прежде, чем мы непосредственно приступим к разработке модуля - прочитайте оговорки (это важно на самом деле):
- Правильным было бы упаковать все стили и JS-скрипты в сам модуль, как это сделать - я обязательно напишу, а в данном конкретном примере мне это не нужно, поскольку я писал реальный модуль под реальный шаблон, и все стили модуля - уже есть в шаблоне, дублировать их не имеет смысла.
- При разработке модуля правильным будет создавать языковые файлы и прописывать константы. Я опять же не стал этого делать, почему - потому что на данный момент мне это не нужно.
- Я не использовал в модуле вспомогательный класс helper, поскольку модуль совсем простенький.
Остальное будем рассматривать по ходу статьи.
Техническое задание
И так, наша задача заключается в следующем: необходимо разработать модуль вопросов и ответов (F.A.Q.) для CMS Joomla. Его задача - выводить вопросы и ответы согласно имеющемуся статичному html-шаблону. Также в админке должна быть реализована возможность быстрого добавления вопросов и ответов на них. Вот в принципе и все, а ниже скриншот того, что нам необходимо получить:
HTML-код модуля, который мы будем реализовывать выглядит следующим образом:
Теперь давайте разберем подробнее, что же мы видим. А видим мы что наш модуль использует классы Bootstrap. Также мы видим, что каждый вопрос и ответ на него расположены в блоке card и что эти блоки повторяются:
Теперь давайте посмотрим, что же именно нам нужно менять в каждом из блоков, а что можно оставить в шаблоне:
- Нам нужно вбивать вопрос в админке
- Нам нужно вбивать ответ в админке
Это самое основное, но помимо этого мы видим в нашем коде несколько ID:
И так, первый из них - это ID блока с вопросом id="headingOne", этот же ID дублируется в ответе в атрибуте aria-labelledby="headingOne". Атрибут aria-labelledby предназначен для связи между объектами и метками, он содержит ID меток для того, чтобы вспомогательные технологии (средства чтения экрана и т.д.) могли собрать все метки в каталог. Поэтому нам обязательно нужно, помимо вопроса и ответа, поле ID.
Второй идентификатор, который мы видим в data-target="#collapseOne" - дублируется еще в двух местах, и если вы заглянете в документацию Bootstrap, то увидите, что благодаря именно этому идентификатору у нас работает collapse, то есть схлопывание/развертывание. Если, к примеру, мы возьмем data-target с первого вопроса и назначим этот ID третьему ответу, то при нажатии на первый вопрос нам откроется третий ответ.
Также внизу в коде мы видим еще и два изображения плюс описания для них. Для них мы тоже создадим возможность редактирования с админки.
Подытожим: нам в админке модуля должны быть доступны следующие вещи:
- Написать вопрос
- Написать ответ на этот вопрос
- Написать ID для data-target
- Написать ID для aria-labelledby
- Выбрать изображения
- Написать два описания для них
На этом пока все, но к нашему исходному шаблону мы еще вернемся.
Файловая структура модуля для Joomla
Файловая структура стандартного модуля имеет следующий вид:
- mod_faq.xml
- mod_faq.php
- helper.php
- tmpl
-- default.php
mod_faq.xml - это файл-манифест, он содержит всю информацию о модуле, файлы, которые должны быть установлены, а также параметры конфигурации модуля.
mod_faq.php - единая точка входа для модуля, он вызывает helper, а также подключает макет вывода модуля, кроме этого там же мы подключаем стили и так далее
helper.php - файл, который содержит вспомогательный класс для выполнения необходимых расчетов, обращения к БД и так далее
tmpl - папка с файлами макетов
default.php - макет вывода информации
В нашем случае файловая структура будет немного другой:
- mod_faq.xml
- faq_field.xml
- mod_faq.php
- tmpl
-- default.php
Мы убрали helper, поскольку у нас простой модуль, и можно обойтись без вспомогательного класса, а все необходимые скрипты выполнить либо в mod_faq.php (мы так и сделаем), либо даже в default.php. Кроме того, как я говорил выше - мы не будем подключать стили нашего модуля, поскольку пишем модуль для имеющегося шаблона, в котором эти стили уже есть, нам остается только написать классы и все. По этой же причине я не стал использовать конструкцию $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx')); , которая получает суффикс класса модуля из параметров (Внимание: по хорошему следовало бы ее использовать, поскольку вполне вероятно, что в дальнейшем вы захотите добавить какие-то классы для модуля).
faq_field.xml - специальный файл, который мы затронем позже, пока что просто создайте его и все.
Файл mod_faq.xml
Для начала я приведу весь код файла, а потом уже разберемся что за что отвечает:
Мною коряво были обрисованы некоторые блоки, сейчас расскажу о них подробнее:
Блок 1 - здесь мы указываем тип расширения module (мы знаем что еще существуют и плагины, и компоненты, и шаблоны), указываем версию Joomla и клиента, в нашем случае это site
Блок 2 - здесь мы указываем информацию о модуле: его имя, автора, дату создания, копирайт, лицензию и описание
Блок 3 - здесь между тегами <files> и </files> мы пишем все файлы, которые должны быть установлены
Блок 4 - это как раз и есть все параметры модуля
Блок 5 - группа полей, которую мы назвали "Настройки". Тут мы видим поля для выбора наших изображений, а также поля для их описаний. Подробнее о стандартных полях Joomla - читайте здесь.
Блок 6 - Выделен отдельно, поскольку мы используем любопытный тип поля - subform, о нем расскажем подробно ниже
Вот так в админке выглядят группы полей в виде отдельных вкладок:
Если вы обратили внимание, то должны были заметить, что я не использовал в манифесте ни языковые константы, а также не указывал директорию с языковыми файлами. Так делать не нужно, правильнее все же использовать языковые константы!
Файл faq_field.xml, тип поля subform и наш html-шаблон
И вот теперь мы наконец-то подобрались к самому интересному. Вернемся вновь к нашему шаблону. Мы можем пойти по простому пути и создать например 10 полей типа text вопросов и столько же ответов (по этому пути пошли разработчики нагугленных мною примеров). Потом они конструкцией if...endif проверяли поле на наличие в нем данных и в зависимости от этого выводили данные. На мой взгляд это неправильно: нам нужно чтобы мы прямо в админке могли добавить сколько угодно полей, либо же удалить. И тут нам на помощь приходит тип поля subform
subform - предоставляет возможность использовать XML-формы друг в друге или повторно использовать существующие формы внутри текущей формы, доступен с версии Joomla 3.6
И так, чтобы использовать subform мы создаем файл faq_field.xml, в котором пишем следующее:
Что мы видим на этом рисунке? Мы видим четыре поля, которые нас интересуют: вопрос, ответ, ID1 и ID2. Все, на этом мы оставляем этот файл и возвращаемся к основному mod_faq.xml к конструкции fieldset name="questions"
<fieldset name="questions" label="Вопросы и ответы">
<field name="chatids" type="subform"
formsource="modules/mod_faq/faq_field.xml" multiple="true"
label="Добавить вопрос/ответ"
description="Добавить вопрос/ответ"
layout="joomla.form.field.subform.repeatable-table"
/>
</fieldset>
Теперь разберем все это подробнее. Тип поля мы указываем subform. formsource - путь к нашей XML-форме, относительно корня joomla. Дальше идет такая важная штука как multiple="true". Параметр "true" позволяет использовать нашу форму множество раз.
Дальше идут обычные label и description, а вот затем мы видим layout="joomla.form.field.subform.repeatable-table". Это макет нашей формы, я воспользовался стандартным макетом, вы можете взять свой, или же совсем без макета.
Вот так в админке выглядит наш fieldset name="questions":
Вы видите, как удобно нам теперь создавать/удалять новые поля, на этом мы бросаем наши XML-файлы и переходим к разбору файла mod_faq.php
Файл mod_faq.php
Для начала давайте посмотрим на сам код файла:
И так, строчка defined( '_JEXEC' ) or die( 'Restricted access' ) в целях безопасности запрещает доступ к файлу извне joomla.
Строчкой require( JModuleHelper::getLayoutPath( 'mod_faq' ) ) мы подключаем макет вывода, в нашем случае это default.php в папке tmpl
А теперь подробнее рассмотрим часть кода, которую я на рисунке пометил цифрой 2.
Когда мы с вами смотрели наш исходный html-шаблон, то там мы заметили, что блоки вопросов и ответов практически идентичны по структуре. Поэтому нам имеет смысл перебирать их через foreach. Для этого мы создаем пустой массив:
$result = ""
Затем мы пишем строку foreach ($params['chatids'] as $item), где $params['chatids'] - это как раз наши данные, полученные с поля subform c именем 'chatids'. Вообще, все параметры модуля доступны в params.
Следующая строка $item = (array) $item; может вызвать недоумение, но я сейчас попробую объяснить, для чего это было сделано. Дело в том, что если мы сделаем var_dump ($params['chatids']), то увидим следующее:
stdClass - общий пустой класс PHP, полезен для анонимных объектов, динамических свойств и т.д. Строкой $item = (array) $item - мы получаем массив данных:
Вот так выглядит var_dump ($item) после преобразования. Теперь нам удобно работать с получившимся массивом. (примечание: к этому вопросу я вернусь спустя некоторое время, поскольку есть смутное ощущение, что тут можно было сделать по другому)
Далее мы берем и добавляем в наш массив $result с помощью конкатенации строк классы нашего блока с вопросом и ответом, а сами данные получаем из $item. Обратите внимание на класс collapsed для ссылки, в нашем шаблоне в первом блоке стоял класс collapse, а в ответе - collapse show. Мы же подставляем классы со второго блока, для того, чтобы при открытии страницы все вопросы были "схлопнуты" (как раз за это отвечает класс collapsed, если там будет collapse - все наши блоки будут развернуты, а это неправильно). Более подробно можно найти в официальной документации Bootstrap.
На этом с этим файлом все, а мы наконец-то переходим к нашему макету default.php
Файл default.php
Вот так выглядит наш макет:
Вы видите, что мы точно также в начале файла закрыли доступ извне, далее мы оставили с нашего html-шаблона код, который не будет меняться, и простым <?php echo $result;?> мы в нужном месте вывели наш массив $result, в котором все наши вопросы и ответы. Если обратите внимание на цифру 2 на рисунке, то вы увидите echo $params['media'] и другие поля, которые также доступны в params по имени. Там мы, согласно нашего шаблона, выводим картинки и их alt.
Все, все наши файлы готовы, нам остается лишь упаковать их в ZIP-архив и стандартно установить через Менеджер расширений Joomla.
На этом пока все, критика приветствуется. Также должен сказать о том, что со временем эта статья стопроцентно будет обновлена, так как есть моменты, которые мне не нравятся, возможно имеет смысл сделать по-другому. Но это - потом.
Напоминаю, что вопросы можно задать в группе https://t.me/newqosgroup