Опубликован: 02.10.2012 | Уровень: специалист | Доступ: платный
Лекция 1:

Архитектура Joomla. Базовые сведения

Лекция 1: 123 || Лекция 2 >
Аннотация: Коротко описана архитектура Joomla. Рассмотрены предопределенные константы, языковые файлы, реализация паттерна "фабрика", работа с HTTP-запросом, объектом JApplication, создание панелей инструментов.

Цель лекции: Изучить базовые сведения об архитектуре Joomla. Получить представление о функционировании такого типа расширений как компоненты.

Предисловие

Важнейшим источником сведений о программировании под Joomla является официальная документация к этой системе [5]. Однако на момент составления данного курса эта документация является достаточно неполной, особенно с учетом того, что ряд статей относится к старой версии Joomla (1.5). Код расширений, написанных под Joomla 1.5, несколько отличается от кода, написанного под недавно вышедшие версии Joomla 1.6, 1.7 и 2.5.

Руководство по разработке компонента на официальном сайте Joomla начинается сразу с написания кода в соответствии с архитектурой MVC (Модель – Вид – Представление). Такой подход едва ли удобен, так как значительно легче для студента было бы начать с изучения основ программирования под Joomla, с изучения основных классов фреймворка этой системы и лишь потом переходить на архитектуру MVC. Более удобный для обучения подход применяется в книге [3]. Она строится от простого к сложному: сначала рассматривается разработка простого компонента без использования классов, реализующих MVC, а затем происходит переход на эту архитектуру. Поэтому в практической части данного курса мы будем следовать порядку изложения этой книги. Кроме того, большая часть программного кода, составляющего практическую часть данного курса, основана на листингах из этой книги. Однако исходные коды, взятые из книги [3], написаны под Joomla 1.5 и устарели. Для данного курса они были изменены для использования в Joomla 1.7 и перенесены на другую предметную область. Переход на Joomla 1.7 потребовал расмотрения в практической части курса таких отсутствовавших в [3] вопросов, как создание пунктов меню в панели управления, использование языковых файлов. Большее внимание уделено работе с навигационной цепочкой сайта.

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

Следует отметить отсутствие литературы о программировании под Joomla на русском языке. Исключением является небольшое руководство [6], написанное тем же Джозефом ЛеБланком и опубликованное в русском переводе в электронном журнале PHPInside за ноябрь – декабрь 2005 г.

Отметим также книгу [2], которая тоже рассматривает программирование для старой версии Joomla.

В начале 2012 г. вышла книга [1], восполняющая недостаток сведений о программировании под Joomla 1.6/1.7/2.5.

Введение

Для системы управления контентом Joomla созданы тысячи расширений. Тем не менее, использовать готовое решение не всегда целесообразно. Стороннее расширение может быть слишком дорогим или перегружать сервер ненужными для конкретной задачи функциями. Для нестандартной задачи готового решения может вовсе не найтись.

Иногда достаточно воспользоваться одним из конструкторов контента (CCK) для Joomla, позволяющих создавать свои шаблоны для материалов. Однако и CCK - не панацея, и возможно, что и он окажется бессилен. В таком случае возникает необходимость написать собственное расширение.

Может случиться, что готовое решение начнет работать некорректно и придется искать в нем ошибку. Тогда, чтобы разобраться в его коде, программисту понадобится знание принципов построения расширений под Joomla.

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

Архитектура Joomla

Фреймворк Joomla состоит из трех уровней ( рис. 1.1):

  1. уровень фреймворка;
  2. уровень приложения;
  3. уровень расширений.
Фреймворк Joomla

Рис. 1.1. Фреймворк Joomla

Уровень фреймворка обеспечивает базовую функциональность Joomla с помощью набора библиотек и плагинов и собственно фреймворка Joomla:

  • фреймворк Joomla (или "ядро") - набор классов, обеспечивающих базовую функциональность Joomla. Названия этих классов начинаются с буквы "J" и говорят сами за себя: JDatabase, JUser, JForm, JEditor и т.д.;
  • библиотеки требуются для работы фреймворка или сторонних расширений;
  • плагины расширяют функциональность фреймворка.

Уровень приложения состоит из приложений, которые расширяют абстрактный класс JApplication. Приложение - глобальный объект, использующийся для обработки запросов.

В этот уровень входят следующие приложения:

  • JInstallation запускается при установке Joomla. После завершения установки необходимо удалить директорию installation, которая как раз и содержит данное приложение. В дальнейшем установка расширений выполняется с помощью приложения JAdministrator;
  • JAdministrator управляет всеми функциями для администрирования Joomla;
  • JSite отвечает за компоновку и отображение фронтенда;
  • XML-RPC позволяет администрировать сайт Joomla удаленно.

Уровень расширений состоит из расширений фреймворка Joomla и приложений:

  • компоненты - основной тип расширений Joomla. При каждом обращении к Joomla происходит вызов соответствующего компонента. Например, при отображении какой-либо страницы сайта происходит вызов компонента com_content;
  • модули используются для отображения небольших фрагментов контента, обычно в левой или правой колонке или верхней или нижней областях страницы;
  • плагины позволяют зарегистрировать функции и классы для обработки каких-либо событий, вызванных Joomla, например, поиск по сайту;
  • языковые файлы позволяют представить контент Joomla на нескольких языках;
  • шаблоны отвечают за внешний вид сайта.

Фронтенд и бэкенд

Joomla делится на фронтенд - часть сайта, доступная пользователю, и бэкенд - систему администрирования сайта. Соответственно, в Joomla всего две точки входа - index.php для фронтенда и /administrator/index.php для бэкенда. Чтобы вызвать какой-либо установленный на сайте компонент, необходимо передать его имя (с префиксом "com_") скрипту index.php или /administrator/index.php в переменной option в строке URL. Например, переход по ссылке http://localhost/joomla/index.php?option=com_banners приведет к вызову компонента banners.

Большинство компонентов для Joomla делятся на фронтенд и бэкенд, и их код распределяется по двум папкам, каждая из которых называется по схеме com_<имя компонента>. В каждой из этих папок должен находиться файл, являющийся точкой входа, и называющийся так же, как компонент, т.е. <имя компонента>.php. Схематически это можно изобразить так:

administrator
|- components
..|- com_mycomponent
....|- mycomponent.php
components
..|- com_mycomponent
....|- mycomponent.php
    

Предопределенные константы

В Joomla определен ряд констант, хранящих значения путей: JPATH_BASE - путь к корневой директории текущего приложения; JPATH_ROOT - путь к корневой директории сайта, JPATH_COMPONENT - путь к директории компонента, JPATH_COMPONENT_SITE - путь к фронтенду компонента, JPATH_COMPONENT_ADMINISTRATOR - путь к бэкенду компонента и т.д. Полный их список можно найти в документации. Все эти константы возвращают значения абсолютных путей в файловой системе. Если вам необходимо получить путь для использования в URL, следует воспользоваться методом JURI::base().

В файле index.php, расположенном в корневой директории Joomla, определена константа _JEXEC. Большинство PHP-файлов, написанных под Joomla, начинаются с выражения

defined('_JEXEC') or die('Restricted access');
    

Данное выражение осуществляет проверку, был ли файл, в котором оно записано, вызван из Joomla. Таким путем запрещается доступ к файлу извне, чтобы предотвратить взлом сайта.

Еще одна популярная константа Joomla - DS, разделитель директорий, принятый в конкретной операционной системе (например, прямой или обратный слеш).

Языковые файлы

Joomla позволяет создать мультиязыковый сайт, задавая для каждого пользователя язык сайта и панели управления. Данная возможность реализована следующим образом: в кодах расширений при необходимости вывести на экран какой-либо заранее известный текст (например, сообщение об успешном выполнении запроса пользователя) вместо этого текста записывается его эквивалент (ключ). Для каждого языка, поддерживающегося данным расширением, создаются языковые файлы, которые хранят переводы для всех ключей, встретившихся в кодах расширения. Например, для ключа "COM_MYCOMPONENT_HELLO_WORLD" перевод на английский язык может задаваться как "Hello, world!", на русский - "Здравствуй, мир!", на французский - "Bonjour le monde!" и т.д.

Языковые файлы фронтенда хранятся в папке /language/<ln-LN>, где <ln-LN> - код языка по стандарту RFC3066. Файл должен называться по схеме <ln-LN>.<префикс><имя расширения>.ini, где префикс зависит от вида расширения: "com_" (компонент), "mod_" (модуль), "tpl_" (шаблон) и т.д. Например, путь к языковому файлу компонента contact для русского языка следующий:/language/ru-RU/ru-RU.com_contact.ini

Языковые файлы бэкенда хранятся в папке /administrator/language/<ln-LN>.

Кроме файлов .ini, для расширения должен также быть создан файл *.sys.ini, в котором могут храниться переводы сообщений, выводящихся после установки расширения, переводы пунктов меню, создающихся для компонента в панели управления, переводы параметров компонента и переводы надписей, выводящихся в менеджере расширений. Например, путь к файлу .sys.ini компонента contact для русского языка выглядит так: /administrator/language/ru-RU/ru-RU.com_contact.sys.ini

Содержимое языкового файла состоит из пар "ключ-значение" и, при необходимости, комментариев. Пустые строки игнорируются. Комментарии начинаются с символа ";". Например:

; Это комментарий
    

Ключ - это строка для перевода, а значение - это перевод данной строки на заданный язык. Ключ отделяется от значения знаком равенства:

КЛЮЧ=Значение
    

Например:

COM_CONTACT="Контакты"
    

Ключ должен быть записан в верхнем регистре и не должен содержать пробелы. Все ключи во фронтенде должны начинаться со строки <префикс><имя расширения>_, например:

COM_CONTACT_CHANGE_CONTACT_BUTTON
    

Значение (перевод ключа) должно быть заключено в двойные кавычки. Если значение к тому же содержит двойные кавычки, то они должны быть записаны в виде HTML-сущности, например, &quot.

Для использования переводов применяются методы статического класса JText _(), sprint() и printf().

Простейший способ вывести перевод строки - использовать метод JText::_(), который просто переводит строку, переданную ему параметром. Например:

echo JText::_('COM_MYCOMPONENT_HELLO_WORLD');
    

Если перевод для заданной строки не будет найден в языковых файлах, то метод _() вернет саму эту строку. Перед поиском строка будет переведена в верхний регистр, поэтому не имеет значения, в каком регистре ее записать в коде.

Если в строку необходимо включить какие-либо значения, то используются методы JText sprintf() и printf(), аналогичные одноименным функциям в PHP. Их параметрами являются строка для перевода и любое количество аргументов для подстановки в переведенную строку. Сами параметры не будут переведены. Методы sprintf() и printf() различаются тем, что printf() выводит получившуюся строку на экран и возвращает ее длину, а sprintf() возвращает саму строку и ничего не выводит.

Например, если в языковом файле ru-RU.com_mycomponent.ini задано

COM_MYCOMPONENT_THANK_YOU="Спасибо за Ваше сообщение, %s!"
    

а в коде расширения имеется строка

echo JText::sprintf('COM_MYCOMPONENT_THANK_YOU', 'Вася');
    

то результатом будет вывод на экран строки "Спасибо за Ваше сообщение, Вася!".

Аргументы задаются так же, как в одноименных функциях PHP: %s означает строку, %d - целое число, %f - число с плавающей точкой и т.д.

Паттерн "фабрика" (класс JFactory)

В Joomla существует статический класс JFactory, реализующий паттерн "фабрика". Методы данного класса (getApplication(), getDate(), getDbo(), getDocument(), getLanguage(), getURI(), getUser(), getMailer(), getEditor() и др.) позволяют получить доступ к соответствующим глобальным объектам фреймворка (JApplication, JDate, JDatabase, JDocument, JLanguage, JURI, JUser, JMail, JEditor и др.), ряд которых будет рассмотрен далее.

Рассмотрим пример получения доступа к объекту JUser:

$user =& JFactory::getUser();
if ($user->guest)
  echo "Вы не вошли на сайт";
else
  echo "Вы вошли на сайт как ".$user->name;
    

Обратите внимание на знак амперсанда перед вызовом метода getUser(). Мы получаем ссылку на объект-представитель текущего пользователя. Если пропустить амперсанд, то будет создана копия этого объекта и изменения, которые мы будем в ней производить, не затронут оригинал.

HTTP-запрос (класс JRequest)

В Joomla вместо непосредственного использования глобальных массивов $_GET, $_POST, $_FILES, $_COOKIE, $_ENV, $_SERVER и $_REQUEST удобнее применять класс JRequest. Его методы пропускают данные, введенные пользователем, через фильтр во избежание инъекций.

Для получения переменных запроса GET/POST используется метод mixed getVar(string $name, string $default=null, string $hash='default', string $type='none', int $mask=0), где:

$name имя переменной;
$default значение по умолчанию, которое вернет метод getVar(), если значение переменной не задано;
$hash источник данных, по умолчанию они будут получены из массива $_REQUEST. Явное указание массива GET или POST повысит безопасность кода;
$type тип ожидаемого значения:
INT
INTEGER
FLOAT
DOUBLE
BOOL
WORD
ALNUM допускает только буквенно-цифровые значения;
CMD
BASE64 допускает только те символы, которые могут быть представлены в кодировке base64 (т.е. a-z, A-Z, 0-9, /, + и =);
STRING
ARRAY
PATH исключает возможность атаки. Например, если исходное значение содержало /./ или /../, то вместо него метод вернет пустую строку;
USERNAME удаляет управляющие символы (0x00 - 0x1F), 0x7F, <, >, ", ', % и &;
$mask константа, задающая опции фильтрации:
JREQUEST_NOTRIM не удалять пробелы в начале и конце строки;
JREQUEST_ALLOWRAW без какой-либо фильтрации;
JREQUEST_ALLOWHTML не удалять HTML-код, но пропустить значение через фильтр (в частности, удалить опасные теги - script, applet, iframe и др.).

Эти константы не заключаются в кавычки, т.к. это не строки, а статические переменные. Если ни одной опции не задано, то HTML-теги, а также пробелы в начале и конце строки будут удалены.

Пример:

$answer = JRequest::getVar('answer', 'no answer', 'post', 'string', JREQUEST_ALLOWRAW);
    

Если нужно получить весь массив переменных запроса в отфильтрованном виде, используется

mixed get(string $hash='default', int $mask=0)
    

Например, получим массив $_POST:

$arr = JRequest::get('post');
    

Для присвоения переменным запроса значений используется метод string setVar(string $name, string $value=null, string $hash='method', bool $overwrite=true)

Если $overwrite=false и в запросе уже задано значение переменной $name, то метод просто вернет само это значение. В противном случае переменной будет присвоено значение $value, а метод вернет старое значение $name.

Пример:

JRequest::setVar('var1', 'val1');
    

Класс JRequest содержит также методы, позволяющие получить значение определенного типа: getBool(), getCmd(), getFloat(), getInt(), getString(), getWord().

Приложение (класс JApplication)

Очередь сообщений

В Joomla существует очередь сообщений - массив строк, которые будут выведены на экран при следующей загрузке какой-либо страницы. Стандартными являются три типа сообщений ( рис. 1.2): message (собственно сообщение), notice (предупреждение) и error (ошибка):

Типы сообщений

Рис. 1.2. Типы сообщений

Для добавления сообщений в очередь используется метод void enqueueMessage(string $msg, [string $type = 'message']), где:

$msg - текст сообщения;
$type - тип сообщения.

Например:

global $app;
$app->enqueueMessage('Message');
$app->enqueueMessage('Notice', 'notice');
$app->enqueueMessage('Error', 'error');
        

В данном примере $app - это глобальный объект JApplication.

Для получения копии очереди сообщений используется метод array getMessageQueue(). Например, для предыдущей очереди из трех сообщений он возвращает массив:

Array 
(
  [0]=>Array
   (
    [message]=>Message
    [type]=>message
  )
  [1]=>Array 
  (
    [message]=>Notice
    [type]=>notice
  )
  [2]=>Array
  (
    [message]=>Error
    [type]=>error
  )
)
        
Лекция 1: 123 || Лекция 2 >
Кирилл Гусаров
Кирилл Гусаров

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

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

- myquestions.php;

- admin.myquestions.php

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

/components/com_myquestions/myquestions.php;

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

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

Игорь Чернышов
Игорь Чернышов
Россия
Елена Новикова
Елена Новикова
Россия