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

SEF-ссылки. Классы ядра JDocument, JUser

< Лекция 4 || Лекция 5: 12 || Лекция 6 >
Аннотация: Рассмотрен процесс генерации и декодирования SEF-ссылок для какого-либо компонента. Рассмотрены классы для работы с документом и с данными текущего или любого другого пользователя.

Цель лекции: Изучить принципы работы с SEF-ссылками, сгенерированными в компоненте по собственному шаблону. Ознакомиться с некоторыми методами классов JDocument и JUser.

Генерация SEF-ссылок (класс JRoute)

В Joomla существует возможность создавать SEF-ссылки (Search-Engine Friendly) вида www.mysite.ru/one/two/three, удобные и для посетителей, и для поисковых систем. Для этого используется единственный метод класса JRoute, переводящий внутреннюю ссылку, генерируемую Joomla, в SEF-ссылку:

string _(string $url, bool $xhtml=true, int $ssl=null)
    

где

$url - абсолютный или относительный URI;
$xhtml - заменять ли амперсанды на "&amp;";
$ssl - при $ssl=1 полученный URI будет начинаться с протокола https://, в противном случае - http://.

Данный метод разбирает $url на пары "ключ-значение" и сохраняет результаты разбора в массиве. Из этого массива удаляется элемент option. Его значение добавляется к новому URL в качестве первого сегмента. Затем производится поиск файла /components/com_<option>/router.php. В этом файле должны находиться две функции: функция для генерации SEF-ссылок (<имя компонента>BuildRoute()) и функция для декодирования элементов SEF-ссылок (<имя компонента>ParseRoute()). Метод JRoute::_() вызовет функцию <имя компонента>BuildRoute() и передаст ей массив, полученный при разборе $url. Функция вернет массив $segments. Метод JRoute::_() добавит к новому URL все элементы этого массива, разделив их слэшами. Если в запросе останутся какие-либо необработанные переменные, они будут добавлены в конец URL.

Допустим, метод JRoute::_() получит на вход ссылку вида

index.php?option=com_mycomponent&var1=value1&var2=value2&…&varN=valueN
    

Тогда он передаст в функцию <имя компонента>BuildRoute() ассоциативный массив

Array([option]=>com_mycomponent [var1]=>value1 [var2]=>value2... [varN]=>valueN)
    

причем пары "ключ-значение" будут расположены в том порядке, в котором они были в исходной ссылке. Задача функции <имя компонента>BuildRoute() - выбрать необходимые пары и сохранить в результирующем массиве только значения, но так, чтобы впоследствии можно было восстановить соответствующие им ключи. Это достигается использованием какого-либо фиксированного порядка. Функция вернет массив вида

Array([0]=>value1 [1]=>value2 … [N-1]=>valueN)
    

из которого затем будет создана SEF-ссылка

component/mycomponent/value1/value2/…/valueN
    

Впоследствии при щелчке на какой-либо SEF-ссылке произойдет обратный процесс. Будет вызван метод <имя компонента>ParseRoute(), который получит на вход массив

Array([0]=>value1 [1]=>value2 ... [N-1]=>valueN)
    

и вернет ассоциативный массив:

Array([var1]=>value1 [var2]=>value2 … [varN]=>valueN)
    

который Joomla установит в качестве переменных HTTP-запроса. Таким образом, посетители сайта и поисковые системы увидят SEF-ссылки, а компонент будет работать с обычным набором пар "ключ-значение".

Обратите внимание, что SEF-ссылка не содержит никакой информации о том, как называются ключи массива. Чтобы их можно было восстановить, функция генерации ссылок и функция их декодирования должны неявно задавать шаблон SEF-ссылок для конкретного компонента. В данном примере подразумевается шаблон, который можно сформулировать вербально так: "переменные записываются в следующем порядке: var1, var2, … varN".

Шаблон может быть более сложным. Например, его структура может меняться в зависимости от задачи, т.е. от значения входящей в него переменной task.

В простейшем случае содержимое файла router.php выглядит так:

<?php
defined('_JEXEC') or die ('Restricted access');
function <имя компонента>BuildRoute(&$query)
{
  $segments = array();
  if (isset($query['var1']))
  {
    $segments[] = $query['var1'];
    unset($query['var1' ]) ;
  }
...
  if(isset($query['varN' ]))
  {
    $segments[] = $query['varN'];
    unset($query['varN']);
  }
  return $segments;
}
function <имя компонента>ParseRoute($segments)
{
  $vars = array();
  $vars['var1'] = @$segments[0];
...
  $vars['varN'] = @$segments[1];
  return $vars;
}
?>
    

Обратите внимание, что массив $query должен быть передан в функцию <имя компонента>BuildRoute() по ссылке. По мере заполнения массива $segments обработанные элементы удаляются из массива $query с помощью unset(). Любые элементы, которые останутся в массиве $query после работы функции <имя компонента>BuildRoute(), останутся и в URL. Если мы передадим $query по значению, вызовы функции unset() будут действовать только на локальную копию этого массива и все элементы старого URL будут появляться после SEF-сегментов.

Документ (класс JDocument)

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

Получение ссылки на глобальный объект JDocument:

$document =& JFactory::getDocument();
    

Этот объект хранит название, описание, язык, направление текста, дату модификации, кодировку и некоторые другие значения. Класс JDocument содержит несколько методов для получения этих значений: getTitle(), getDescription(), getLanguage(), getDirection(), getModifiedDate(), getCharset() и др. Соответственно, методы для задания этих значений называются setTitle(), setDescription() и т.д. и принимают в качестве аргумента новое значение.

Получение значения мета-тега

string getMetaData(string $name, bool $http_equiv = false)
        

где

$name - название тега;
$http_equiv - относится ли этот мета-тег к группе http-equiv (например, Content-Type, Refresh и др.).

Примеры:

echo $document->getMetaData('content-type', true);
echo $document->getMetaData('keywords', false);
        

Изменение значения мета-тега

void setMetaData(string $name, string $content, bool $http_equiv = false, bool $sync = true)
        

где

$content - значение атрибута content;
$sync - синхронизировать ли тег content-type с MIME-типом документа.

Пример:

$document->setMetaData('content-type','text/html',true,true);
        

Добавление скриптов и каскадных таблиц стилей

Перечисленные ниже методы добавляют в секцию <head> соответствующие теги.

Добавление ссылки на скрипт:

void addScript(string $url, string $type = "text/javascript", bool $defer = false, bool $async = false)
        

где

$url - URL скрипта;
$type - тип скрипта (text/javascript, text/vbscript и т.д.);
$defer - добавлять ли к тегу <script> атрибут defer="defer";
$async - добавлять ли к тегу <script> атрибут async="async".

Пример:

$document->addScript('/components/com_mycomponent/js/script.js');
        

Добавление непосредственно текста скрипта

void addScriptDeclaration(string $content, string $type = 'text/javascript')
        

где

$content - текст скрипта;
$type - тип скрипта.

Пример:

$document->addScriptDeclaration('alert("Hello World")');
        

Добавление внешней таблицы стилей

void addStyleSheet(string $url, string $type = 'text/css', string $media = null, array $attribs = array())
        

где

$url - URL файла CSS;
$type - MIME-тип файла;
$media - значение атрибута media (screen, print, projection и др.);
$attribs - массив других атрибутов тега <link>.

Пример:

$document->addStyleSheet('/components/com_mycomponent/css/style.css');
        

Добавление внутренней таблицы стилей

void addStyleDeclaration(string $content, string $type = 'text/css')
        

где

$content - код CSS;
$type - значение атрибута type будущего тега <style>.

Пример:

$document->addStyleDeclaration('.myclass { color: red; }');
        

Пользователь (класс JUser)

Пользователь, просматривающий сайт, представлен объектом класса JUser, доступ к которому можно получить через метод getUser() класса JFactory:

$user =& JFactory::getUser();
    

Чтобы получить доступ к объекту, представляющему какого-либо другого пользователя, необходимо передать в метод getUser() id или логин этого пользователя:

$user =& JFactory::getUser(42);
$user =& JFactory::getUser('admin');
    

Поля класса JUser

JUser имеет ряд полей, для которых определен уровень доступа public и к которым поэтому можно обращаться непосредственно. Наиболее важные из них перечислены ниже ( таблица 5.1).

Таблица 5.1. Некоторые public-поля класса JUser
Поле Описание
block Равно 1, если пользователь заблокирован
email E-mail пользователя
guest Равно 1, если пользователь является гостем, т.е. не залогинен
id ID пользователя
lastvisitDate Дата и время последнего входа пользователя в систему
name Имя пользователя
params Настройки пользователя
registerDate Дата и время регистрации аккаунта пользователя
sendEmail Равно 1, если пользователь согласен получать сообщения с сайта по электронной почте
username Логин пользователя

Например, выведем приветствие для залогиненного пользователя:

if ($user->guest)
  echo "Пожалуйста, войдите в систему или зарегистрируйтесь";
else
  echo "Здравствуйте, {$user->name}! Последний раз вы были на сайте ".JHTML::_('date',$user->lastvisitDate);
        

Получение и изменение настроек пользователя

mixed getParam(string $key, mixed $default = null)
mixed setParam(string $key, mixed $value)
        

где

$key - ключ параметра;
$default - значение параметра по умолчанию;
$value - устанавливаемое значение параметра.
setParam() - возвращает предыдущее значение параметра.

Пример:

echo $user->getParam('language','ru-RU');
$user->setParam('language','en-GB');
        
< Лекция 4 || Лекция 5: 12 || Лекция 6 >
Кирилл Гусаров
Кирилл Гусаров

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

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

- myquestions.php;

- admin.myquestions.php

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

/components/com_myquestions/myquestions.php;

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

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

Татьяна Калинина
Татьяна Калинина
Россия