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

Архитектура MVC в компонентах Joomla

< Лекция 5 || Лекция 6: 123 || Лекция 7 >
Аннотация: Рассмотрены принципы реализации архитектуры MVC в компоненте и классы Joomla, использующиеся для этого.

Цель лекции: Ознакомиться с основами применения архитектуры MVC при разработке компонентов.

Взаимодействие элементов архитектуры MVC в Joomla

MVC ("Model - View - Controller") - это набор паттернов проектирования, который предполагает разделение программного кода на три группы:

  • модели (model) используются для хранения данных. В Joomla модели реализуются с помощью абстрактного класса JModel;
  • представления (view) генерируют вывод для заданной информации с помощью шаблона. В Joomla реализуются с помощью абстрактного класса JView;
  • контроллеры (controller) получают команды от пользователя и управляют моделями и представлениями для выполнения этих команд. В Joomla реализуются с помощью абстрактного класса JController.

Приблизительно схема взаимодействия этих групп в коде Joomla представлена на следующей диаграмме последовательности ( рис. 6.1 на основе иллюстрации из книги [4, p.246]).

Взаимодействие контроллера, модели и представления

Рис. 6.1. Взаимодействие контроллера, модели и представления

В файле /components/com_<имя компонента>/<имя компонента>.php находится код для создания контроллера, например:

$controller = new MyComponentController();
$controller->execute(JRequest::getVar('task'));
$controller->redirect();
    

В HTTP-запросе задается задача, представление и, при необходимости, другие данные. Метод execute() вызывает метод вашего контроллера, который называется так же, как и заданная задача. Если задача не указана, то ей будет присвоено значение "display", следовательно, будет выполнен метод display(). Для этой и всех остальных задач, которые должен выполнять ваш компонент, необходимо создать в классе контроллера одноименные методы. Наконец, метод redirect() перенаправляет пользователя к другому URL, если такой URL был задан в каком-либо методе при выполнении контроллера.

В простейшем случае класс контроллера описан в файле /components/com_<имя компонента>/controller.php, в более сложных случаях этих классов может быть несколько. Каждый из них должен быть производным от JController:

class MyComponentController extends JController
{
  …
  function display()
  {
    …
    parent::display();
        …
  }
…
}
    

Вы можете переопределить метод JController::display() в своем классе контроллера. Метод display() базового класса вызывает методы getView(), getModel(), а также метод display() заданного представления. getView() возвращает объект-представитель заданного представления, getModel() - заданной модели. По умолчанию используются те представление и модель, название которых совпадает с именем контроллера.

Далее нас будет интересовать работа метода display() заданного представления.

Каждый класс представления описан в файле /components/com_<имя компонента>/views/<имя представления>/view.html.php и является производным от JView. В этом классе может быть перегружен метод display(), чтобы вызвать метод класса модели для загрузки данных:

class MyComponentViewMyView extends JView
{
  function display($tpl=null)
  {
    $model=&$this->getModel();
    $list=$model->getList();
    $this->assignRef('list', $list);
    parent::display($tpl);
  }
}
    

Каждый класс модели описан в файле /components/com_<имя компонента>/models/<имя модели>.php и является производным от JModel. В этом классе может находиться метод для загрузки данных из базы данных или другого источника:

class ModelMyComponentMyModel extends JModel
{
  var $_somelist = null;
  function getList()
  {
    if (!$this->_somelist)
    {  
      $query = "SELECT * FROM #__mycomponent";
      $this->_somelist = $this->_getList($query, 0, 0);
    }
    return $this->_somelist;
  }
}
    

Итак, метод класса представления display() вызывает метод класса модели для загрузки данных и сохраняет результат в какой-либо переменной, которая затем с помощью метода JView::assignRef() связывается с текущим представлением. Наконец, вызывается метод базового класса JView::display(), который загружает файл заданного шаблона при помощи перехвата выходного потока.

Шаблон находится в папке /components/com_<имя компонента>/views/<имя представления>/tmpl. В его коде осуществляется вывод на экран переменных текущего представления. Например:

<table width="100%">
  <?php
    foreach($this->list as $l)
      echo '<tr><td>'.$l->data.'</td></tr>';
  ?>
</table>
    

Так выглядит простейший вариант взаимодействия моделей, представлений и контроллеров.

Классы Joomla для реализации MVC

JModel

Одно из полей класса JModel - объект-представитель базы данных $_db. Таким образом, для выполнения запросов к базе данных в методах производных от JModel классов нужно обращаться непосредственно к этому полю, не получая новой ссылки на глобальный объект JDatabase:

$this->_db->setQuery($query);
$this->_db->query();
        
Получение списка каких-либо объектов и количества записей
array _getList(string $query, int $limitstart=0, int $limit=0)
int _getListCount(string $query)
            

где

$query - запрос к базе данных;
$limitstart - смещение;
$limit - количество записей.

Например:

$query = "SELECT * FROM #__mycomponent";
$list = $this->_getList($query, 0, 0);  
$count = $this->_getListCount($query);
            

JView

Joomla поддерживает возможность добавления нескольких моделей к одному представлению. В таком случае ссылки на объекты-представители моделей будут храниться в поле _models объекта JView. Для добавления модели используется метод

JModel setModel(object &$model, bool $default = false)
        

где

$model - имя модели (т.е. имя соответствующего класса);
$default - назначить ли ее моделью по умолчанию.

Метод возвращает добавленную модель.

Получение ссылки на объект-представитель одной из добавленных к представлению моделей
JModel getModel(string $name = null)
            

где $name - имя модели.

Например, добавим в коде контроллера к представлению SomeView модели Model1 и Model2:

$view = &$this->getView('SomeView', 'html');
$view->setModel($this->getModel('Model1'), true);
$view->setModel($this->getModel('Model2'));
            
Получение данных из зарегистрированной модели или поля представления
mixed get(string $property, string $default = null)
            

где

$property - название метода модели, который требуется вызвать, или поля представления. В первом случае будет вызван метод get<Название метода>() - обратите внимание на заглавную букву;
$default - если данные должны быть получены из модели, то $default - имя модели. Если требуется получить значение поля, то $default - значение, которое будет возвращено, если такое поле отсутствует.

Например, если в модели, заданной для текущего представления по умолчанию, есть метод getValue(), то получить в классе представления возвращаемое им значение можно так:

$temp = &$this->get('value');
            
Связывание переменной с представлением
bool assignRef(string $key, mixed &$val)
            

где

$key - имя поля объекта-представителя представления. Не может начинаться со знака подчеркивания;
$val - значение поля.

Пример:

$view->assignRef('somevar', $someval);
            
Выполнение и отображение скрипта шаблона
void display(string $tpl = null)
string loadTemplate(string $tpl = null)
            

где $tpl - имя файла шаблона. Конкретное имя файла зависит от значений имени и расширения макета, заданных в классе, по умолчанию это соответственно default и php. Если вы хотите изменить эти значения, используйте методы setLayout() и setLayoutExt(). Будет произведен поиск файла <имя макета>_<$tpl>.<расширение макета> или при $tpl=null <имя макета>.<расширение макета>.

display() выводит на экран результат работы скрипта шаблона, а loadTemplate() только возвращает этот результат. При ошибке display() возвращает объект Exception.

Например:

echo $view->loadTemplate('mytpl');
            

отобразит результат выполнения скрипта /components/com_<имя компонента>/views/<имя представления>/tmpl/default_mytpl.php.

JController

Выполнение задачи путем вызова одноименного метода производного класса
mixed execute(string $task)
            

где $task - имя задачи. Если такой задачи не найдется, будет выполнена задача "__default".

Метод возвращает значение, возвращаемое вызванным методом, или false в случае ошибки.

Например, код

$controller->execute('addItem');
            

приведет к вызову метода addItem() контроллера $controller.

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

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

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

- myquestions.php;

- admin.myquestions.php

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

/components/com_myquestions/myquestions.php;

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

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