Joomla отношение многие к многим

25.12.2015

Иногда, в Joomla, необходимо сделать поле с множественным выбором, например, для указния нескольких тегов к посту

Создание "поля"

Для начала, нужно создать поле у нужного нам компонента, например, /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


Категории: CMS Joomla 3.X, Joomla
Пометки: Joomla field поле с множественным выбором
Яндекс.Метрика