Иногда, в Joomla, необходимо сделать поле с множественным выбором, например, для указния нескольких тегов к посту
Joomla отношение многие к многим
25.12.2015
Создание "поля"
Для начала, нужно создать поле у нужного нам компонента, например, /administrator/components/com_NAME/models/fields/sopartners.php . Данный файл будет отвечать за получение списка из БД и вывода его на форму.
sopartners.php (Download)
<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
// Подключаем тип поля list.
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('list');
/**
* Класс поля формы
*/
class JFormFieldSOPartners extends JFormFieldList
{
/**
* Тип поля.
*
* @var string
*/
protected $type = 'SOPartners';
/**
* Мозможено ли выбрать несколько вариантов
*
* @var mixed
*/
protected $multiple_select = FALSE;
/**
* Method to get certain otherwise inaccessible properties from the form field object.
*
* @param string $name The property name for which to the the value.
*
* @return mixed The property value or null.
*
* @since 3.2
*/
public function __get($name)
{
switch ($name)
{
case 'multiple_select':
return $this->$name;
}
return parent::__get($name);
}
/**
* Method to set certain otherwise inaccessible properties of the form field object.
*
* @param string $name The property name for which to the the value.
* @param mixed $value The value of the property.
*
* @return void
*
* @since 3.2
*/
public function __set($name, $value)
{
switch ($name)
{
case 'multiple_select':
$this->$multiple_select = (string) $value;
break;
default:
parent::__set($name, $value);
}
}
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
*
* @return boolean True on success.
*
* @see JFormField::setup()
* @since 3.2
*/
public function setup(SimpleXMLElement $element, $value, $group = null)
{
$return = parent::setup($element, $value, $group);
if ($return)
{
$this->multiple_select = (string) $this->element['multiple_select'];
}
return $return;
}
/**
* Method to get the field input markup for a generic list.
* Use the multiple attribute to enable multiselect.
*
* @return string The field input markup.
*
* @since 11.1
*/
protected function getInput()
{
if($this->multiple_select)
{
// Без этого не считает поле массивом и передает только одно значение
$this->name = $this->name.'[]';
$this->multiple = 1;
}
return parent::getInput();
}
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @since 1.6
*/
public function getOptions()
{
$options = array();
$db = JFactory::getDBO();
$query = $db->getQuery(true)
->select('id As value, name As text, isPartner')
->from('#__users AS a')
->where('a.isPartner = 1')
->order('a.name');
// Get the options.
$db->setQuery($query);
$data=$db->loadObjectList();
try
{
$options = $db->loadObjectList();
}
catch (RuntimeException $e)
{
JError::raiseWarning(500, $e->getMessage());
}
// Merge any additional options in the XML definition.
// $options = array_merge(parent::getOptions(), $options);
array_unshift($options, JHtml::_('select.option', '0', JText::_('--не указан--')));
return array_merge(parent::getOptions(), $options);
}
}
стоит обратить внимание на
protected function getInput()
{
// Без этого не считает поле массивом и передает только одно значение
$this->name = $this->name.'[]';
$this->multiple = 1;
return parent::getInput();
}
- без этого выбрать из списка можно будет только одно значение
Сохранение и загрузка выбранных тегов
Вносим дополнения в файл нужной нам модели, нашего компонента: /administrator/components/com_NAME/models/items.php
model.item.php (Download)
<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
/**
* Модель soCertification Items.
*/
class soCertificationModelItem extends JModelAdmin
{
/**
* Метод для получения данных, которые должны быть загружены в форму.
*
* @return mixed Данные для формы.
*/
protected function loadFormData()
{
// Проверка сессии на наличие ранее введеных в форму данных.
$data = JFactory::getApplication()->getUserState($this->option . '.edit.item.data', array());
if (empty($data))
{
$data = $this->getItem();
if($data->id)
{
$oModel = JModelLegacy::getInstance('rel_items2tags', 'soCertificationModel');
$data->tags_list = $oModel->getTags($data->id, true);
}
}
return $data;
}
/**
* Method to save the form data.
*
* @param array $data The form data.
*
* @return boolean True on success, False on error.
*
* @since 12.2
*/
public function save($data)
{
// ...
// Oddler \/
$bStore = FALSE;
if($isNew)
{
$table->ordering = $table->id;
$bStore = TRUE;
}
$oModel = JModelLegacy::getInstance('rel_items2tags', 'soCertificationModel');
$oModel->saveTags($table->id, $data['tags_list']);
if($bStore)
{
$table->store();
}
// Oddler /\
// ...
}
}
Таблица
Также нужно создать файл таблицы, для связи с нашей БД: /administrator/components/com_NAME/tables/rel_items2tags.php
rel_items2tags.php (Download)
<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
/**
* Модель soCertification Items.
*/
class soCertificationModelRel_items2tags extends JModelAdmin
{
/**
* Возвращает ссылку на объект таблицы, всегда его создавая.
*
* @param string $type Тип таблицы для подключения.
* @param string $prefix Префикс класса таблицы. Необязателен.
* @param array $config Конфигурационный массив. Необязателен.
*
* @return JTable Объект JTable.
*/
public function getTable($type = 'Rel_items2tags', $prefix = 'soCertificationTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Метод для получения формы.
*
* @param array $data Данные для формы.
* @param boolean $loadData True, если форма загружает свои данные (по умолчанию), false если нет.
*
* @return mixed Объект JForm в случае успеха, в противном случае false.
*/
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm(
$this->option . '.item', 'item', array('control' => 'jform', 'load_data' => $loadData)
);
if (empty($form))
{
return false;
}
return $form;
}
/**
* Метод сохраняет все теги для элемента.
*
* @param int $id_item Идентификатор элемента для которого сохраняются тэги
* @param array $aTags массив тэшов.
*
* @return null
*/
public function saveTags($id_item, &$aTags)
{
if(count($aTags))
{
$db = JFactory::getDBO();
// Удаляем старые связи
$query = $db->getQuery(true);
$query->delete()
->from('#__so_certification_rel_items_tags')
->where('id_item='.$id_item)
;
$db->setQuery($query);
$db->execute();
// Добавляем новые
foreach($aTags as $key => $val)
{
$oTable = JTable::getInstance('rel_items2tags', 'soCertificationTable');
$oTable->id_item = $id_item;
$oTable->id_tag = $val;
$oTable->store();
}
}
}
/**
* Метод возвращает все теги для элемента.
*
* @param int $id_item Идентификатор элемента.
*
* @return array массив объектов.
*/
public function getTags($id_item, $bOnlyId = FALSE)
{
$db = JFactory::getDBO();
$sFields = $bOnlyId?'id':'*';
$sSql = 'SELECT '.$sFields.' FROM #__so_certification_tags WHERE id IN(SELECT id_tag FROM #__so_certification_rel_items_tags WHERE id_item='.$id_item.')';
$db->setQuery($sSql);
if ($bOnlyId)
{
$aRet = array();
$aTMP = $db->loadObjectList();
if(count($aTMP))
{
foreach($aTMP as $oRow)
{
$aRet[] = $oRow->id;
}
}
return $aRet;
}
else
{
return $db->loadObjectList();
}
}
}
Вывод на форме в административном разделе
В файл /administrator/components/com_NAME/models/forms/items.xml добавляем:
File "/home/public/oddler.ru/www/images/com/soblog/items/538/items.xml" not exists