Опубликован: 02.10.2012 | Доступ: свободный | Студентов: 1916 / 85 | Длительность: 11:48:00
Теги: joomla, mvc, php, xhtml, xml
Лекция 3:

Генерация элементов HTML (класс JHTML)

< Лекция 2 || Лекция 3: 123 || Лекция 4 >

Практика

Обработка категорий

В единственном вопросе, который хранится в нашей базе, в поле id_cat стоит значение 1. Оно должно означать id категории. Добавим таблицу и код для работы с категориями.

Создание таблицы для категорий

Выполните следующий SQL-запрос, чтобы создать таблицу для хранения категорий:

CREATE TABLE `jos_myquestions_categories`
(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`desc` TEXT NOT NULL DEFAULT ''
)
            

Добавьте записи в эту таблицу:

INSERT INTO `jos_myquestions_categories` VALUES (NULL,'Без категории',''), 
 (NULL,'Риторические вопросы','Вопросы, не требующие ответа')
            

Зайдите в phpMyAdmin и убедитесь, что таблица jos_myquestions_categories содержит две записи ( рис. 3.11).

Таблица базы данных, хранящая данные о категориях

Рис. 3.11. Таблица базы данных, хранящая данные о категориях

Таким образом, сейчас все вопросы, для которых в поле id_cat стоит значение 1, относятся к категории "Без категории".

Создание класса таблицы

Создайте файл /administrator/components/com_myquestions/tables/category.php:

<?php
defined('_JEXEC') or die('Restricted access');
class TableCategory extends JTable
{
  var $id = null;
  var $name = null;
  var $desc = null;

  function __construct(&$db)
  {
    parent::__construct('#__myquestions_categories', 'id', $db);
  }
}
?>
            
Вывод списка категорий

Добавьте в файл admin.myquestions.php функцию showCategories():

function showCategories($option)
{
    $db =& JFactory::getDbo();
    $query = "SELECT * FROM #__myquestions_categories";
    $db->setQuery($query);
    $rows = $db->loadObjectList();
    if ($db->getErrorNum())
    {
        echo $db->stderr();
        return false;
    }
    HTML_questions::showCategories($option, $rows);
}
            

Эта функция аналогична функции showQuestions(), рассмотренной ранее.

В файл admin.myquestions.html.php в класс HTML_questions добавьте еще одну функцию:

  function showCategories($option, &$rows) 
{ 
?>
  <form action="index.php" method="post" name="adminForm">
    <table class="adminlist">
      <thead>
        <tr>
          <th width="20">
            <input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count($rows);?>);"/>
          </th>
          <th class="title" width="30%"><?php echo JText::_('COM_MYQUESTIONS_CATEGORY_NAME');?></th>
          <th><?php echo JText::_('COM_MYQUESTIONS_CATEGORY_DESC');?></th>
        </tr>
      </thead> 
      <?php
        jimport('joomla.filter.output');
        $k = 0;       
        for  ($i = 0,  $n = count($rows); $i < $n;  $i ++)       
        {
          $row = &$rows[$i];
          $checked = JHTML::_('grid.id', $i, $row->id);
          $link = JFilterOutput::ampReplace('index.php?option=' .$option . '&task=editcat&cid[]='. $row->id);
      ?>
      <tr class="<?php echo "row$k";?>">
        <td><?=$checked?></td>
        <td><?='<a href="'.$link.'">'.$row->name.'</a>'?></td>
        <td><?=$row->desc?></td>
      </tr>
      <?php
        $k = 1 - $k;
      }
      ?>
    </table>
    <input type="hidden" name="option" value="<?php echo $option;?>"/>
    <input type="hidden" name="task" value=""/>
    <input type= "hidden" name="boxchecked" value="0"/>
  </form>
<?php
}
            

Данная функция также аналогична одноименной функции для отображения списка вопросов.

Добавьте в переключатель switch в файле admin.myquestions.php обработку новой задачи:

case 'showcat':
   showCategories($option);
   break;
            

Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_CATEGORY_NAME="Название категории"
COM_MYQUESTIONS_CATEGORY_DESC="Описание категории"
            

Перейдя по ссылке http://localhost/joomla/administrator/index.php?option=com_myquestions&task=showcat, вы уже можете увидеть список категорий.

Однако пока над списком будет отображаться старая панель инструментов, которую мы создали для списка вопросов. Поэтому необходимо также создать новые панели инструментов для работы с категориями. Откройте файл toolbar.myquestions.php и добавьте в переключатель switch следующий код:

case 'showcat':
  TOOLBAR_myquestions_categories::_DEFAULT();
  break;
            

Как видите, мы добавили обработку задачи showcat - отображение списка категорий. Соответственно, вызывается функция _DEFAULT() класса TOOLBAR_myquestions_categories. Напишем код этого класса. Добавьте в файл toolbar.myquestions.html.php код:

class TOOLBAR_myquestions_categories
{
  function _DEFAULT()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::addNew('addcat');
    JToolBarHelper::editList('editcat');     JToolBarHelper::deleteList
    (JText::_('COM_MYQUESTIONS_TOOLBAR_REMOVE_CATEGORIES_CONFIRMATION'), 
     'removecat');  }
}
            

Таким образом, панель инструментов для списка категорий будет содержать три кнопки: "Создать", "Изменить" и "Удалить".

Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES="Управление категориями вопросов"
COM_MYQUESTIONS_TOOLBAR_REMOVE_CATEGORIES_CONFIRMATION="Вы действительно хотите удалить эти категории?"
            

Теперь по ссылке http://localhost/joomla/administrator/index.php?option=com_myquestions&task=showcat видим список категорий ( рис. 3.12).

Список категорий в бэкенде

увеличить изображение
Рис. 3.12. Список категорий в бэкенде
Создание, редактирование и удаление категорий

При нажатии на кнопки "Создать" или "Изменить", расположенные над списком категорий, должна отображаться другая панель инструментов. Для этого добавьте в класс TOOLBAR_myquestions_categories функцию _NEW():

class TOOLBAR_myquestions_categories
{
  function _NEW()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::save('savecat');
    JToolBarHelper::apply('applycat');    
    JToolBarHelper::cancel('showcat');
  }
  function _DEFAULT()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE_CATEGORIES'), 
     'generic.png');
    JToolBarHelper::addNew('addcat');
    JToolBarHelper::editList('editcat');
    JToolBarHelper::deleteList(JText::_('COM_MYQUESTIONS_TOOLBAR_REMOVE_CONFIRMATION'),
      'removecat');
  }
}
            

Запишем в файле toolbar.myquestions.php, что при обработке задач addcat и editcat должна отображаться панель инструментов _NEW. Измените код этого файла так:

<?php
defined('_JEXEC') or die('Restricted access');
require_once(JApplicationHelper::getPath('toolbar_html'));
switch($task)
{
  case 'reply':
    TOOLBAR_myquestions::_REPLY();
    break;
  default:
    TOOLBAR_myquestions::_DEFAULT();
    break;
  case 'showcat':
    TOOLBAR_myquestions_categories::_DEFAULT();
    break;
  case 'addcat':
  case 'editcat':
    TOOLBAR_myquestions_categories::_NEW();
    break;
}
?>
            

Теперь добавим обработку всех перечисленных в файле toolbar.myquestions.html.php задач. Откройте файл admin.myquestions.php и добавьте в переключатель switch код:

case 'addcat':
case 'editcat':
    editCategory($option);
    break;
case 'savecat':
case 'applycat':
    saveCategory($option, $task);
    break;
case 'removecat':
    removeCategories($option);
    break;
            

Добавьте перечисленные функции в файл admin.myquestions.php:

function editCategory($option)
{
    $row =& JTable::getInstance('Category','Table');
    $cid = JRequest::getVar('cid', array(0), '', 'array');
    $id = $cid[0];
    $row->load($id);
    HTML_questions::editCategory($row, $option);
}
function saveCategory($option, $task)
{
    $row =& JTable::getInstance('category', 'Table');
    if (!$row->bind(JRequest::get('post')))
    {
        echo "<script> alert('".$row->getError()."');
          window.history.go(-1); </script>\n";
        exit();
    }
    $row->desc = JRequest::getVar('desc', '', 'post', 'string', JREQUEST_ALLOWRAW);
    
    if (!$row->store())
    {
        echo "<script> alert('".$row->getError()."'); 
         window.history.go(-1); </script>\n";
        exit();
    }
    
    global $app;
    if ($task == 'savecat')
        $app->redirect('index.php?option='.$option.'&task=showcat', 
         JText::_('COM_MYQUESTIONS_CATEGORY_SAVED'));
    else
        if ($task == 'applycat')
            $app-
            >redirect('index.php?option='.$option.'&task=editcat&cid[]='.$row-
            >id, JText::_('COM_MYQUESTIONS_CATEGORY_SAVED'));
    }
    function removeCategories($option)
    {
        global $app;
        $cid = JRequest::getVar('cid', array(), '', 'array');
        $db =& JFactory::getDbo();
        if(count($cid))
        {
            $cids = implode(',', $cid);
            $query = "DELETE FROM #__myquestions_categories WHERE id IN ($cids)";
            $db->setQuery($query);
            if (!$db->query())
            {
                echo "<script> alert('".$db->getErrorMsg()."'); 
                 window.history.go(-1); </script>\n";
            }
        }
        $app->redirect('index.php?option=' . $option . '&task=showcat', 
         JText::_('COM_MYQUESTIONS_CATEGORY_DELETED'));
    }
            
Листинг .

Добавьте в файл admin.myquestions.html.php в класс HTML_questions метод editCategory() для отображения формы редактирования категории:

function editCategory ($row, $option)
{
  $editor =& JFactory::getEditor();
  ?>
  <form action = "index.php" method="post" name="adminForm"
    id="adminForm">
    <fieldset class="adminform">
      <table class="admintable" width=100%>
        <tr>
          <td width="100" class="key">
              <?php echo JText::_('COM_MYQUESTIONS_CATEGORY_NAME');?>:
          </td>
          <td>
            <input class="text_area" type="text" name="name" id="name" 
             size="50" maxlength="255" value="<?php echo $row->name;?>"/>
          </td>
        </tr>
        <tr>
          <td width="100" class="key">
            <?php echo JText::_('COM_MYQUESTIONS_CATEGORY_DESC');?>:
          </td>
          <td>
            <?php
              echo $editor->display('desc',  $row->desc,'100%', '250', '40', '10');?>
          </td>
        </tr>
      </table>
    </fieldset>
    <input type="hidden" name="id" value="<?php echo $row->id;?>"/>
    <input type="hidden" name="option" value="<?php echo $option;?>"/>
    <input type="hidden" name="task" value=""/>
  </form>
<?php
}
            

Наконец, добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_CATEGORY_SAVED="Категория сохранена"
COM_MYQUESTIONS_CATEGORY_DELETED="Категории успешно удалены"
            

Убедитесь, что все кнопки обеих панелей инструментов работают корректно.

Присвоение вопросу какой-либо категории

Добавим в форму ответа на вопрос выпадающий список для выбора категории.

Откройте файл admin.myquestions.php и измените код функции replyToQuestion() следующим образом:

    function replyToQuestion($option)
{
    $row =& JTable::getInstance('Question','Table');
    $cid = JRequest::getVar('cid', array(0), '', 'array');
    $id = $cid[0];
    $row->load($id);
    $db = &JFactory::getDBO();
    $query = 'SELECT name AS text, id AS value FROM #__myquestions_categories';
    $db->setQuery($query);
    $categories = $db->loadObjectList();
    $list_cat = JHTML::_('select.genericlist',  $categories,  'id_cat', 
    ' class="inputbox" ', 'value', 'text', $row->id_cat);
    HTML_questions::replyToQuestion($row, $option, $list_cat);
}
            

В файле admin.myquestions.html.php измените прототип функции HTML_questions::replyToQuestion() так:

function replyToQuestion ($row, $option, $list_cat)
            

Наконец, в коде этой функции измените фрагмент, в котором раньше выводилось текстовое поле с id категории, так:

<tr>
  <td width="100" class="key">
    <?php echo JText::_('COM_MYQUESTIONS_CATEGORY');?>:
    </td>
  <td>
    <?=$list_cat?>
  </td>
</tr>
            

Перейдите к странице ответа на вопрос и убедитесь, что отображается выпадающий список для выбора категории ( рис. 3.13).

Выбор категории вопроса в бэкенде

Рис. 3.13. Выбор категории вопроса в бэкенде

Ключевые термины

JHTML - класс для вывода элементов XHTML.
JHTMLBehavior - поддерживающий класс, который позволяет вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления.
JHTMLEmail - поддерживающий класс, содержащий метод для скрытия адреса электронной почты в целях его защиты от спам-ботов.
JHTMLForm - поддерживающий класс, содержащий метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак.
JHTMLGrid - поддерживающий класс, позволяющий вывести в таблице в панели управления такие элементы, как чекбокс, пиктограмма для переключения состояния "опубликовано"/"не опубликовано", отобразить заголовок столбца как ссылки для сортировки по этому столбцу и др.
JHTMLImage - поддерживающий класс, содержащий методы для поиска изображения в фронтенде и бэкенде.
JHTMLList - поддерживающий класс для создания списков некоторых конкретных значений.
JHTMLSelect - поддерживающий класс для генерации кода списков.
Основной метод класса JHTML - метод JHTML::_(), который вызывает метод, определяющийся его первым параметром, и передает ему свои остальные параметры.
Поддерживающие классы - классы для вывода элементов XHTML и поведений Javascript.

Краткие итоги

Joomla содержит методы для генерации и отображения элементов XHTML и поведений JavaScript. Эти методы вызываются с помощью метода JHTML::_(). По первому параметру данный метод определяет, какой метод необходимо вызвать, а остальные параметры передаются в этот метод. Таким образом могут быть вызваны как методы самого класса JHTML, так и методы поддерживающих классов.

Методы класса JHTML позволяют вывести следующие элементы: календарь, форматированную дату, элементы <iframe>, <img>, <a>, <script>, <link> и всплывающую подсказку.

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

  • JHTMLBehavior позволяет вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления.
  • JHTMLEmail содержит метод для скрытия адреса электронной почты в целях его защиты от спам-ботов.
  • JHTMLForm содержит метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак.
  • JHTMLGrid позволяет вывести в таблице в панели управления такие элементы, как чекбокс, пиктограмма для переключения состояния "опубликовано"/"не опубликовано", отобразить заголовок столбца как ссылки для сортировки по этому столбцу и др.
  • JHTMLImage содержит два метода для поиска изображения в фронтенде и бэкенде соответственно.
  • JHTMLList используется для создания списков некоторых конкретных значений.
  • JHTMLSelect используется для генерации кода списков.

Вопросы

  1. Каким образом работает метод JHTML::_()?
  2. Какие элементы могут быть отображены с помощью класса JHTML?
  3. Для чего используется класс JHTMLBehavior?
  4. Для чего используется класс JHTMLEmail?
  5. Для чего используется класс JHTMLForm?
  6. Код каких элементов генерируют методы класса JHTMLGrid?
  7. В чем преимущество использования класса JHTMLImage?
  8. Для чего используются классы JHTMLList и JHTMLSelect?

Упражнения

Адаптируйте код из раздела "Практика" для своего варианта (см. список вариантов в "Варианты заданий для лабораторных работ" ).

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Кирилл Гусаров
Кирилл Гусаров

В разделе "Первые папки и файлы. Добавление пунктов меню"

предлагается создать две файла:

- myquestions.php;

- admin.myquestions.php

с соответствуюшими адресами:

/components/com_myquestions/myquestions.php;

- /administrator/components/com_myquestions/admin.myquestions.php;

Так вот, при создании файла "admin.myquestions.php" В админке выдает ошибку - "Компонент не найден", а при переименовании его на  "myquestions.php" в последующем шаге, в админке не выводятся кнопки редактирования. 
Проверил кодировку, проверил правильность пути к файлам, пересохранил указанный код. Скажите что я делаю не так или в чем может быть причина?