Печать

Параметры расширений Joomla, API хранения, вызова, объединения.

Для хранения практически всей информации о сайте Joomla использует базу данных MySQL. Она позволяет хранить значительные объемы данных, при этом предоставляет нам удобный интерфейс для взаимодействия с ней. Компонент обычно создает хотя бы одну таблицу для хранения своей информации. Например, данные материалов компонента "com_content" хранятся в "jos_content" таблице (где "jos_" это префикс названия всех таблиц Joomla).

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

Типы параметров в компонентах Joomla

Параметры по умолчанию

Это глобальные настройки задаются один раз на весь компонент, и как правило используются для одного конкретного сайта.

Параметры пункта меню

Пункт меню так же может иметь индивидуальные параметры для компонента. Обычно они перекрывают глобальные настройки расширения. Таким образом два разных пункта меню могут ссылаться на один и тот же материал, при этом материал может отображаться по разному, в зависимости от выбранного вида (не нужно путать с MVC), т.е. типом меню и настройками непосредственно самого пункта.

Специфические параметры определенного элемента

Наконец для каждого элемента  (например материала для "com_content") можно установить индивидуальные настройки, которые будут перекрывать настройки из меню, а тот в свою очередь глобальные настройки компонента. 

Сохранение параметров и их значений в Joomla

Обычно, все параметры хранятся в базе данных MySQL в одном поле типа text. Различные параметры разделены символом переноса "\n", т.е. каждый параметр - это отдельная строка. Имя от значения отделяются друг от друга символом "=". Например

параметр1 = параметр1значение
параметр2 = параметр2значение
параметр3 = параметр3значение
параметр4 = параметр4значение

Настройки компонента по умолчанию

Они хранятся в поле "params" таблицы jos_components, в строке соответствующей определенному компоненту, к которому они применяются.

Настройки компонента в пункте меню

Они хранятся в поле "params" таблицы jos_menu, в строке соответствующей конкретному пункту меню, который указывает на компонент.

Параметры конкретного элемента (например материала)

Они хранятся в текстовом поле в таблице, созданной с помощью компонента. Отметим, что нет строгого правила именования этого поля, хотя обычно его тоже называют "params". Не смотря на это, "com_content" например, использует для этого поле с именем "attribs".

Параметры для панели управления Joomla

Joomla предоставляет нам ряд удобств для работы с параметрами компонентов. Для этого все параметры должны быть описаны в файле ".xml" и объединены тегом <param />. Вложенные теги определяются как элементы формы, которая доступна в настройках компонента панели управления.

Настройки компонента при его установки и значения по умолчанию

<install>
...
    <params>
     <param />
         <!-- Например: создадим параметр "font_size" по умолчанию равным "16" -->
          <param name="font_size" default="16" />
          ...
     </params>
     <url addpath="....">
         <param />
     </url>
...
</install>

Каждый элемент формы должен иметь атрибуты "name" и "default". После установки компонента в базу данных запишутся эти значения как умолчания. Однако это не всегда удобно. Можно создать отдельный файл настроек компонента config.xml в корне директории "/administrator/components/com_COMPONENT_NAME/". Структура файла должна выглядеть так как ниже в примере.

<root>
    <params addpath="/administrator/components/com_COMPONENT_NAME/elements">
        <param name="cid" type="JELEMENT_TYPE_NAME" scope="com_COMPONENT_NAME" default="0" label="LABEL" description="DESCRIPTION" />
        <param type="type" name="name" description="description" />
 
        <!--
              Пример: Следующая строка добавит текстовое поле,
              в котором можно будет вписать не более 3х символов и названием "Font size:".  
              Когда пользователь наведет мышью на название,
              то всплывет подсказка с текстом "Please enter the required font size".
              При сохранении, значение введенное в поле сохраниться как "font_size",
              если поле осталось пустым, то сохранится значение по умочанию "10".
        -->
 
        <param type="text" name="font_size" size="3" default="10" label="Font size:" description="Please enter the required font size" />
        ...
    </params>
</root>

В атрибуте "addpath" указывается директория с новыми типами элементов форм, которые можно самостоятенльно определить при разработке. Также этот атрибут можно определить в теге <url>, который обрамляет специальные элементы <param>. Чтобы задействовать новый тип нужно в атрибуте "type" тега <param> указать название класса, который расширяет класс JElement. Класс этот должен быть объявлен в файле с именем класса и расположен в директории "/administrator/components/com_COMPONENT_NAME/elements".

Чтобы получить доступ к форме параметров необходимо прописать следующий код:

JToolBarHelper::preferences( 'com_COMPONENT_NAME');
// Например, для компонента материалов
// вы должны использовать JToolBarHelper::preferences( 'com_content' );

При использовании MVC этот код вписывается в файле "/administrator/components/com_COMPONENT_NAME/views/VIEW_NAME/view.html.php". 

При нажатии на эту кнопку, вы увидите форму настроек компонента, которая создается с помощью файла "config.xml". Обратите внимание, что нет большой необходимости объявлять значения по умолчанию, т.к они впишутся автоматически при установке компонента.

Параметры для определенного пункта меню

Обычно один компонент может иметь несколько представлений, например "категория", "материал", "раздел". И каждый из этих видов имеет свои настройки. Кроме того эти настройки при совпадении имен, могут переопределять глобальные(об это ниже). Форма параметров определена в XML файле, который должен быть расположен по адресу "/components/com_COMPONENT_NAME/views/VIEW_NAME/tmpl/default.xml". Если название Вида не default, то XML-файл должен иметь название как и у файла Вида. Структура файла следующая:

<metadata>
    <layout title="LAYOUT_NAME">
        <message>
             <![CDATA[LAYOUT_DESCRIPTION]]>
        </message>
    </layout>
    <state>
        <name>LAYOUT_NAME</name>
        <description>LAYOUT_DESCRIPTION</description>
        <state>
            ...
            <params>
                <param />
                ...
            </params>
            <url>
               <param />
               ...
            </url>
            <advanced>
                <param />
                ...
            </advanced>
        </state>
</metadata>

За отображение этих форм отвечает административный компонент com_menus. После того как он обработает xml-файл, все что находилось внутри <url> и <params> будет отображено в основных параметрах, соответственно для содержимое <advanced> будет включено в расширенные параметры пункта меню.

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

  • Чтобы переопределить какой-либо глобальный параметр нет необходимости его заново объявлять для меню, он автоматически добавляется из файла "config.xml".
  • Любой элемент <param type="radio" /> будет показан не как переключатель, а как выпадающий список.
  • Раскрывающиеся списки не переопределяются, они объединяются. При этом в список добавляется пункт "Использовать глобальные" и он выбран по умолчанию.

Параметры конкретного элемента компонента

Они определены в файле XML, который может храниться где угодно, но обычно находится в пределах Back-End директории "models" (если вы используете структуру MVC) и назван в зависимости от имени модели, к которой он применяется, например "/administrator/components/com_COMPONENT_NAME/models/MODEL_NAME.xml". Файл XML должен иметь следующую структуру:

<root>
    <params>
         <param />
         ...
    </params>
    <params group="GROUP_NAME">
        <param />
        ...
    </params>
    ...
</root>

Как и в случаях выше, можно вместо тега <root> использовать любой другой, но все же желательно использовать "root". Можно определить несколько групп параметров, указывая в теге <params> атрибут с именем группы. При наличие нескольких одинаковых групп, использоваться в работе будет только первая.

Для того чтобы эти группы отобразились в настройке элемента, в панели управления придется написать небольшой фрагмент кода. Нужно получить доступ к параметрам из базы данных. Для это стоит определиться с местом хранения параметров в базе MySQL и XML-файлом, который будет использоваться для описания формы. Например, будем считать что в $row содержится информация о материале, а в свойстве этого объекта params - сохраненные параметры из базы данных.

$paramsdata = $row->params;
$paramsdefs = JPATH_COMPONENT.DS.'models'.DS.'MODEL_NAME.xml';
$params = new JParameter( $paramsdata, $paramsdefs );
// полученное значение отправляем в виде переменной в файл Вида.
$this->assignRef('params', $params);

Этот код должен находится в файлах Вида (например, view.html.php) в соответствующих папках.

Для отображения параметров в форме слайдера (аккордиона) нужно использовать следующий код в файле шаблона (например, /administrator/com_COMPONENT_NAME/views/VIEW_NAME/tmpl/default.php). Пример слайдера можно увидеть на картинке выше, а реализация идет далее.

// добавляем поддержку аккордеона в шаблоне
jimport('joomla.html.pane');
 
$pane =& JPane::getInstance( 'sliders' );
 
// начало вывода аккордеона
echo $pane->startPane( 'content-pane' );
 
// Первая панель
// Создаем панель с названием SLIDER_PANEL_1_TITLE и id="SLIDER_PANEL_1_NAME"
echo $pane->startPanel( JText::_( 'SLIDER_PANEL_1_TITLE' ), 'SLIDER_PANEL_1_NAME' );
// Отображаем параметры объявленные в <params> (без атрибута "group")
echo $this->params->render( 'params' );
echo $pane->endPanel();
 
// Вторая панель
// Создаем панель с названием SLIDER_PANEL_1_TITLE и id="SLIDER_PANEL_1_NAME"
echo $pane->startPanel( JText::_( 'SLIDER_PANEL_2_TITLE' ), 'SLIDER_PANEL_2_NAME' );
// Отображаем параметры объявленные в <params> с атрибутом group="GROUP_NAME"
echo $this->params->render( 'params', 'GROUP_NAME' );
echo $pane->endPanel();
 
// и т. д. для каждой из групп
 
// конец вывода аккордеона
echo $pane->endPane();

Для того, чтобы сохранить параметры в базу данных нужно перегрузить метод BIND(), который может быть найден в "/administrator/com_COMPONENT_NAME/tables/COMPONENT_NAME.php"

function bind($array, $ignore = '') {
    if (key_exists( 'params', $array ) && is_array( $array['params'] )) {
        $registry = new JRegistry();
        $registry->loadArray( $array['params'] );
        $array['params'] = $registry->toString();
    }
    return parent::bind($array, $ignore);
}

Практическое использование параметров - Лицевая часть

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

С перекрыванием

Следующий фрагмент кода, дает доступ к глобальным настройкам компонента, которые уже перекрыты пунктом меню (если это было возможно).

$params = JComponentHelper::getParams ( 'COMPONENT_NAME' );
// например, для компонента "com_content" код выглядел бы так:
// $params = JComponentHelper::getParams( 'com_content' )

По правилам MVC код должен быть помещен в Вид (view.html.php)

Допустим параметры пункта меню хранятся в свойстве "params" переменной $row (объект пункта меню), тогда чтобы перекрыть глобальные параметры выполним следующее действие.

$params->merge ( new JParameter ( $row->params ) );

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

$my_param_value = $params->get ( 'PARAMETER_NAME' ) ;
// в $my_param_value будет находиться значение из PARAMETER_NAME

Нужно понимать что при использовании метода merge() не получиться перекрывать определенные параметры. Другими словами следующий код не даст вам желаемого результата:

// мы имеем массив, содержащий набор настроек для определенных элементов,
// и в цикле пытаемся изменять значения по умолчанию для этих индивидуальных элементов настроек
// желаемого результата не будет!
foreach ($itemparamsgroup as $itemparams) {
    $params = &JComponentHelper::getParams( 'COMPONENT_NAME' );
    $params->merge( $itemparams );
    echo $params->get( 'PARAMETER_NAME' );
}

Как это правильно делать, читаем ниже.

Без перекрытия (без перегрузки)

Бывают случаи когда разработчикам нет необходимости использовать встроенное перекрытие, а нужно работать отдельно с каждым набором. Это немного сложнее реализовывать. В следующем примере $params будет присвоены параметры по умолчанию, без перекрытия

$component = JComponentHelper::getComponent( 'COMPONENT_NAME' );
$params = new JParameter( $component->params );

Если вам необходимо объединять параметры из определенного пункта меню, то код будет выглядеть примерно так

$menuitemid = JRequest::getInt( 'Itemid' );
if ($menuitemid) {
    $menu = JSite::getMenu();
    $menuparams = $menu->getParams( $menuitemid );
    $params->merge( $menuparams );
}

Это наиболее корректный метод, чем тот что описывается выше. В этом случае можно просто хранить все в смешанном объекте, например так

$itemparams = new JParameter( $row->params );

Таким образом можно гибко управлять настройками компонента. Например, сделать так чтобы компонент игнорировал в определенных случаях глобальные параметры и использовал только то что придет из пункта меню, или наоборот. Но тем не менее, лучше не отходить от стандартного подхода, а в крайнем случае каким-либо способом сообщить пользователю как работает расширение.

Доступ к конкретному значению осуществляется так же как описано чуть выше.

Интересная статья? Поделись ей с другими: