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

Модули. Постраничный вывод информации. Навигационная цепочка

< Лекция 6 || Лекция 7: 12 || Лекция 8 >

Практика

Разработка модуля

Регистрация модуля в базе данных

Модуль, как и компонент, необходимо зарегистрировать в базе данных. Для этого создадим запись в таблицах #__modules и #__extensions. Выполните следующие SQL-запросы:

INSERT INTO jos_modules (title, ordering, position, published, module, showtitle, params) 
VALUES ('Новые вопросы', 1, 'position-7', 1,
 'mod_myquestions', 1, '{"random":"0","items":"3","maxlen":
"100","author":"1","date":"1"}');
INSERT INTO jos_extensions(name,type,element,folder,client_id,manifest_cache,params,custom_data,system_data) 
VALUES('mod_myquestions', 'module', 'mod_myquestions', '', 0, '{"legacy":false,"name":"mod_myquestions",
"type":"module","creationDate":"2012","author":"Me",
"copyright":"","authorEmail":"","authorUrl":"","version":"1.6.0",
"description":"My Questions module","group":""}', '{}', '', '');
            

Если вы обновите фронтенд после выполнения этих запросов, вы заметите, что модуль не появился, несмотря даже на то, что полю published присвоено значение 1. Дело в том, что модуль должен быть не только опубликован, но еще и назначен для каких-либо пунктов меню. Для этого в панели администрирования войдите в меню "Расширения" - "Менеджер модулей" и выберите модуль "Вопросы". В разделе "Привязка к пунктам меню" выберите в выпадающем списке значение "На всех страницах" и нажмите кнопку "Сохранить и закрыть" ( рис. 7.9).

Привязка модуля ко всем страницам

увеличить изображение
Рис. 7.9. Привязка модуля ко всем страницам
Создание модуля

Напишем модуль, который будет выводить ссылки на последние вопросы или на случайный вопрос. Создадим в папке /modules папку mod_myquestions, а в ней - файл mod_myquestions.php:

<?php
defined('_JEXEC') or die ('Restricted access');

$items = $params->get('items', 1);
$maxlen = $params->get('maxlen',100);
$random = $params->get('random', 0);
$q_author = ($params->get('author',1) == 1) ? ", name" : "";
$q_date = ($params->get('date',1) == 1) ? ", date" : "";
  
$db = &JFactory::getDbo();
$query = "SELECT id, question$q_author$q_date FROM #__myquestions WHERE answer <> '' 
AND (published = 1 OR (expiration_date <> '0000-00-00 00:00:00' AND expiration_date > NOW()))";
if ($random)
{
  $orderby = " ORDER BY RAND()";
  $items = 1;
}
else
  $orderby = " ORDER BY date DESC";
$query .= $orderby;
$db->setQuery($query, 0, $items);
$rows = $db->loadObjectList();
foreach($rows as $row)
{
  echo '<a href="'.JRoute::_("index.php?option=com_myquestions&view=question&task=show&
  id=".$row->id).'">'.substr(strip_tags($row->question),0,$maxlen-1).'</a><br/>';
  $addition = array();
  if ($params->get('author',1) == 1)
    $addition[] = $row->name;
  if ($params->get('date',1) == 1)
    $addition[] = JHTML::_('date', $row->date, JText::_('DATE_FORMAT_LC3'));
  if (count($addition))
    echo '<i>'.implode(' ', $addition).'</i><br/>';
}
?>
            

Для установки и считывания параметров может быть использован глобальный объект $params. Когда мы добавили запись в таблицу #__modules, поле params содержало пять значений: random, равное 0, items, равное 3, maxlen, равное 100, author, равное 1, date, равное 1. Их значения мы получаем с помощью метода get(), второй параметр которого - это значение по умолчанию.

Далее задается SQL-запрос для получения из таблицы #__myquestions вопросов, подлежащих публикации. Значения id и question мы получаем в любом случае, а name и date - если в настройках модуля задано, что нужно выводить эти значения. Если нужно выводить один случайный вопрос, то к запросу добавляется "ORDER BY RAND()" и количество записей, которое мы хотим получить, вне зависимости от значения items, заданного в настройках, задается равным 1. В противном случае нужно выводить несколько самых новых вопросов, поэтому к запросу добавляется "ORDER BY date DESC" для сортировки по дате вопроса.

Второй и третий параметры функции setQuery() используются для задания оператора LIMIT, который автоматически добавится к запросу. Таким путем мы получаем из базы данных только первые items записей.

Для каждой полученной записи выводится ссылка на ее просмотр с помощью JRoute::_() и первые maxlen символов, а также, если это разрешено в настройках, имя автора и дата.

Теперь во фронтенде появится модуль, показанный на рис. 7.10. Если модуль не отображается, попробуйте изменить позицию с position-7 на какую-либо другую.

Модуль, отображающий три самых новых вопроса

Рис. 7.10. Модуль, отображающий три самых новых вопроса

С помощью phpMyAdmin измените значение random в настройках модуля mod_myquestions (поле params таблицы #__modules) на "1":

{"random":"1","items":"3","maxlen":"100","author":"1","date":"1"}
            

Теперь модуль выводит один случайный вопрос ( рис. 7.11).

Модуль, отображающий один случайный вопрос

Рис. 7.11. Модуль, отображающий один случайный вопрос

Постраничный вывод информации

Добавим к менеджеру вопросов постраничный вывод списка. Откройте файл /administrator/components/com_myquestions/controller.php и сделайте изменения в коде функции showQuestions() в соответствии с выделенным кодом:

function showQuestions()
  {
    $option = JRequest::getVar('option');
    global $app;
    $limit = JRequest::getVar('limit', $app->getCfg('list_limit'));
    $limitstart = JRequest::getVar('limitstart', 0);

    $db =& JFactory::getDbo();
    $query = "SELECT count(*) FROM #__myquestions";
    $db->setQuery($query);
    $total = $db->loadResult();

    $query = "SELECT * FROM #__myquestions";
    $db->setQuery($query, $limitstart, $limit);
    $rows = $db->loadObjectList();
    if ($db->getErrorNum())
    {
      echo $db->stderr();
      return false;
    }
    jimport('joomla.html.pagination');
    $pageNav = new JPagination($total, $limitstart, $limit);
    HTML_questions::showQuestions($option, $rows, $pageNav);
  }

Значения limit и limitstart мы получаем из HTTP-запроса. Их задает один из методов класса JPagination, который мы вызовем далее. По умолчанию limit берется из настроек Joomla, а limitstart принимается равным 0. Значение total мы получаем из базы данных.

Когда все данные получены, создается объект JPagination, который передается в метод HTML_questions::showQuestions().

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

function showQuestions($option, &$rows, &$pageNav)
{ 
  $maxlen = 100;
?>
  <form action="index.php" method="post" 
  name="adminForm">
    <table class="adminlist">
    ...
    <?php
        jimport('joomla.filter.output');
        $k = 0;       
        for  ($i = 0,  $n = count($rows); $i < $n;  $i ++)       
        {
...
        }
    ?>
      <tfoot>
        <td colspan="10">
          <?php echo $pageNav->getListFooter();?>
        </td>
      </tfoot> 
    </table>
    ...
  </form>
<?php
}
        

Код, полученный с помощью getListFooter(), выведет выпадающий список для выбора количества элементов на странице и ссылки на другие страницы. Название элемента <select> - limit, таким образом, выбранное в выпадающем списке значение попадет в HTTP-запрос как значение переменной limit. Также getListFooter() добавит к форме скрытое поле limitstart, значение которого будет изменяться в зависимости от limit и от нажатой пользователем ссылки на страницу: 0 для первой страницы, limit для второй, 2*limit для третьей и т.д. Таким образом переменная limitstart также будет включена в HTTP-запрос. Из него при переходе на другую страницу эти значения получит функция showQuestions() и использует их при задании нового запроса к базе данных.

Для проверки задайте в настройках сайта длину списка по умолчанию, равную 5, и добавьте вопросы так, чтобы их количество стало больше, чем 5. Примерный вид, который теперь примет список вопросов в бэкенде, показан на рис. 7.12.

Список вопросов с разбиением на страницы

увеличить изображение
Рис. 7.12. Список вопросов с разбиением на страницы

Нацигационная цепочка

Рассмотрим, какие элементы можно отобразить в навигационной цепочке для каждого из представлений нашего компонента:

all - название компонента;
category - название компонента, название категории;
question шаблон default - название компонента, название категории, текст вопроса;
шаблон default_form - название компонента, текст "Задать вопрос".

Как видите, название компонента нужно выводить для всех представлений, поэтому его лучше вывести уже в методе контроллера. В методах представлений будем выводить только те элементы, которые требуют какой-либо информации из модели.

В файле /components/com_myquestions/controller.php измените код методов класса QuestionController так:

function display()
{
  global $app;
  $pathway =& $app->getPathway();
  $pathway->addItem(JText::_('COM_MYQUESTIONS'),
   JRoute::_('index.php?option=com_myquestions'));
…
}

function showForm()
{
  global $app;
  $pathway =& $app->getPathway();
  $pathway->addItem(JText::_('COM_MYQUESTIONS'), 
  JRoute::_('index.php?option=com_myquestions'));
  $pathway->addItem(JText::_('COM_MYQUESTIONS_ADD_QUESTION'));
…
}
        

Изменим метод отображения категории так, чтобы в навигационной цепочке выводилось название категории. Добавьте в метод QuestionViewCategory::display() в файле /components/com_myquestions/views/category/view.html.php код:

global $app;
$pathway =& $app->getPathway();
$pathway->addItem($name_cat);
        

Метод QuestionViewQuestion::display() в файле /components/com_myquestions/views/question/tmpl/default.php измените так:

function display($tpl=null)
{
  if ($tpl !== 'form')
  {
    global $option, $app;
    …
    $pathway =& $app->getPathway();
    $pathway->addItem($question->name_cat, $this->link_cat);
    $pathway->addItem(JString::substr(strip_tags($question->question), 0, 15).'...');
  }
  parent::display($tpl);
}
        

В случае запроса шаблона default_form в данном методе не требуется никаких изменений, так как необходимые элементы навигационной цепочки уже были добавлены в контроллере. По этой же причине не нужно ничего изменять в методе display() представления all.

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

COM_MYQUESTIONS="Моя система &laquo;вопрос &ndash; ответ&raquo;"
        

Навигационная цепочка, которая теперь отображается во фронтенде компонента, показана на рис. 7.13.

Навигационная цепочка на странице с выводом одного вопроса

Рис. 7.13. Навигационная цепочка на странице с выводом одного вопроса

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

JPagination - класс для вывода элементов формы для разбивки на страницы списков элементов.
JPathway - класс для управления навигационной цепочкой.

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

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

Joomla позволяет разбивать длинные списки на страницы, задавая длину списка по умолчанию. Для вывода списков элементов с разбивкой на страницы как в бэкенде, и так и во фронтенде используется класс JPagination. Его методы генерируют HTML-код таких элементов, как счетчик страниц, ссылки на предыдущую/следующую страницу и т.д.

Для управления навигационной цепочкой в Joomla существует объект JPathway. Его методы позволяют добавлять элементы в навигационную цепочку, изменять названия отдельных элементов или весь массив целиком.

Вопросы

  1. Почему разработать модуль легче, чем компонент?
  2. Каким образом Joomla позволяет разбивать длинные списки на страницы?
  3. Какой объект используется для управления навигационной цепочкой?

Упражнения

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

< Лекция 6 || Лекция 7: 12 || Лекция 8 >
Кирилл Гусаров
Кирилл Гусаров

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

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

- myquestions.php;

- admin.myquestions.php

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

/components/com_myquestions/myquestions.php;

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

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