ленивец

 

ВВЕДЕНИЕ

В этой статье я хотел бы рассказать о создании модуля вопросов и ответов для Joomla. В интернете очень много различных примеров, в том числе и в официальной документации, но как правило для новичков бывает сложно самостоятельно разобраться в том или ином примере. Поэтому чем больше существует материалов по данной тематике - тем проще сравнить их между собой, понять принципы, логику и так далее.

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

Используемые навыки: html, css, bootstrap v4, php, xml, joomla

Что вы узнаете:
  • Файловая структура модуля Joomla
  • Использование поля subform
  • Принципы и порядок создания модулей

 

Создание модуля F.A.Q. для CMS Joomla

 Прежде, чем мы непосредственно приступим к разработке модуля - прочитайте оговорки (это важно на самом деле):

  1. Правильным было бы упаковать все стили и JS-скрипты в сам модуль, как это сделать - я обязательно напишу, а в данном конкретном примере мне это не нужно, поскольку я писал реальный модуль под реальный шаблон, и все стили модуля - уже есть в шаблоне, дублировать их не имеет смысла.
  2. При разработке модуля правильным будет создавать языковые файлы и прописывать константы. Я опять же не стал этого делать, почему - потому что на данный момент мне это не нужно.
  3. Я не использовал в модуле вспомогательный класс helper, поскольку модуль совсем простенький.

Остальное будем рассматривать по ходу статьи.

 

Техническое задание

 И так, наша задача заключается в следующем: необходимо разработать модуль вопросов и ответов (F.A.Q.) для CMS Joomla. Его задача - выводить вопросы и ответы согласно имеющемуся статичному html-шаблону. Также в админке должна быть реализована возможность быстрого добавления вопросов и ответов на них. Вот в принципе и все, а ниже скриншот того, что нам необходимо получить:

 

 

HTML-код модуля, который мы будем реализовывать выглядит следующим образом:

 

Теперь давайте разберем подробнее, что же мы видим. А видим мы что наш модуль использует классы Bootstrap. Также мы видим, что каждый  вопрос и ответ на него расположены в блоке card и что эти блоки повторяются:

 

 

Теперь давайте посмотрим, что же именно нам нужно менять в каждом из блоков, а что можно оставить в шаблоне:

  1. Нам нужно вбивать вопрос в админке
  2. Нам нужно вбивать ответ в админке

Это самое основное, но помимо этого мы видим в нашем коде несколько ID:

 

 

И так, первый из них - это ID блока с вопросом id="headingOne", этот же ID дублируется в  ответе в атрибуте aria-labelledby="headingOne". Атрибут aria-labelledby предназначен для связи между объектами и метками, он содержит ID меток для того, чтобы вспомогательные технологии (средства чтения экрана и т.д.) могли собрать все метки в каталог. Поэтому нам обязательно нужно, помимо вопроса и ответа, поле ID.

Второй идентификатор, который мы видим в data-target="#collapseOne" - дублируется еще в двух местах, и если вы заглянете в документацию Bootstrap, то увидите, что благодаря именно этому идентификатору у нас работает collapse, то есть схлопывание/развертывание. Если, к примеру, мы возьмем data-target с первого вопроса и назначим этот ID третьему ответу, то при нажатии на первый вопрос нам откроется третий ответ.

Также внизу в коде мы видим еще и два изображения плюс описания для них. Для них мы тоже создадим возможность редактирования с админки.

Подытожим: нам в админке модуля должны быть доступны следующие вещи:

  1. Написать вопрос
  2. Написать ответ на этот вопрос
  3. Написать ID для data-target
  4. Написать ID для aria-labelledby
  5. Выбрать изображения
  6. Написать два описания для них

На этом пока все, но к нашему исходному шаблону мы еще вернемся.

 

Файловая структура модуля для 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