Иногда, в 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