355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Яна Седова » Разрботка расширений для CMS Joomla » Текст книги (страница 6)
Разрботка расширений для CMS Joomla
  • Текст добавлен: 4 октября 2016, 21:48

Текст книги "Разрботка расширений для CMS Joomla"


Автор книги: Яна Седова



сообщить о нарушении

Текущая страница: 6 (всего у книги 10 страниц)

Какой класс существует для работы с URI?

Для чего может быть использован класс JError?

Каким образом можно работать с датами в Joomla?

Упражнения

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

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

Рассмотрен процесс генерации и декодирования 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 – заменять ли амперсанды на "&"; $ssl – при $ssl=1 полученный URI будет начинаться с протокола https://, в противном случае – http://.

Данный метод разбирает $url на пары «ключ-значение» и сохраняет результаты разбора в массиве. Из этого массива удаляется элемент option. Его значение добавляется к новому URL в качестве первого сегмента. Затем производится поиск файла /components/com_. В этом файле должны находиться две функции: функция для генерации 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выглядит так:

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);

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

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

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

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

где

$url – URL скрипта; $type – тип скрипта (text/javascript, text/vbscript и т.д.); $defer – добавлять ли к тегу n"; exit(); } $row->question = nl2br(htmlspecialchars(JRequest::getVar('question', '', 'post', 'string',JREQUEST_ALLOWRAW), ENT_QUOTES)); $row->IP = getenv('REMOTE_ADDR'); $row->date = &JFactory::getDate()->toFormat(); $row->id_cat = 1; if (!$row->store()) { echo "n"; exit(); } $mailer =& JFactory::getMailer(); $mailer->setSender('[email protected]'); $mailer->addRecipient('[email protected]'); $mailer->setSubject(JText::_('COM_MYQUESTIONS_ADMIN_LETTER_SUBJECT')); $mailer->setBody(JText::sprintf('COM_MYQUESTIONS_ADMIN_LETTER_NEW_QUESTION',$row->question)); $mailer->IsHTML(true); if ($mailer->Send() !== true) { echo "n"; exit(); } global $app; $app-> redirect(JRoute::_('index.php?option='.$option.'&task=view&view=all'), JText::sprintf('COM_MYQUESTIONS_QUESTION_SENT',$row->name)); }

Текст вопроса, введенный пользователем, пропускается через функцию htmlspecialchars(), преобразующую специальные символы в HTML-сущности. Таким путем предотвращается ввод нежелательных HTML-тегов. Затем результат пропускается через функцию nl2br(), вставляющую код разрыва строки
перед каждым переводом строки, чтобы текст вопроса при выводе на веб-странице не слился в одну строку.

IP-адрес пользователя определяется с помощью функции getenv(), которая возвращает значение переменной окружения, в данном случае – REMOTE_ADDR.

По умолчанию вопросу присваивается категория с id, равным 1, то есть "Без категории".

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

COM_MYQUESTIONS_ADD_QUESTION="Задать вопрос" COM_MYQUESTIONS_AUTHOR="Автор" COM_MYQUESTIONS_DATE="Дата вопроса" COM_MYQUESTIONS_QUESTION="Текст вопроса" COM_MYQUESTIONS_CITY="Город" COM_MYQUESTIONS_EMAIL="e-mail" COM_MYQUESTIONS_CATEGORY="Категория" COM_MYQUESTIONS_PUBLISHED="Отображать ли вопрос на сайте" COM_MYQUESTIONS_SENDBUTTON="Отправить вопрос" COM_MYQUESTIONS_QUESTION_SENT="Спасибо, %s! Ваш вопрос отправлен. Он будет опубликован на сайте после получения ответа" COM_MYQUESTIONS_ADMIN_LETTER_SUBJECT="Новый вопрос на сайте" COM_MYQUESTIONS_ADMIN_LETTER_NEW_QUESTION="

Добрый день!

На сайте появился новый вопрос:

%s

" COM_MYQUESTIONS_ADMIN_LETTER_ERROR="Ошибка отправки письма"

Осталось добавить ссылку для написания вопроса. Измените начало функции showCategories() так:

function showCategories($rows, $option) { ?>

&task=showlist'>

&task=showform'>

Теперь на главной странице компонента во фронтенде появилась ссылка " Задать вопрос" (рис. 5.1).

(есть увеличенное изображение)

Рис. 5.1.  Ссылка «Задать вопрос»

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

(есть увеличенное изображение)

Рис. 5.2.  Форма для написания вопроса

После написания вопроса и нажатия кнопки " Отправить вопрос" происходит перенаправление на главную страницу компонента с сообщением об успешной отправке вопроса (рис. 5.3).

(есть увеличенное изображение)

Рис. 5.3.  Сообщение об отправке вопроса

Зайдите в папку <путь к Денверу>/tmp/!sendmailи найдите в ней файл *.eml, содержащий письмо-уведомление администратора о новом вопросе.

SEF

Включите SEF в бэкенде. Для этого перейдите в меню " Сайт" – " Общие настройки" и убедитесь, что переключатель " Включить SEF (ЧПУ)" установлен в " Да". Если вы используете в качестве веб-сервера Apache со включенным mod_rewrite, то вы можете также установить переключатель " Перенаправление URL" в " Да"; тогда из ваших ссылок исчезнет строка " index.php". Вид раздела " Настройки SEO" при включенном mod_rewriteпоказан на рис. 5.4.

Рис. 5.4.  Раздел панели управления «Настройки SEO»

Если ваша конфигурация не позволяет использовать mod_rewrite, SEF-ссылки все равно могут быть построены, но они будут включать строку " index.php", например: ссылка: http://www.mysite.ru/index.php/one/two/three.

Нажмите кнопку " Сохранить и закрыть" для сохранения конфигурации. Если вы используете mod_rewrite, убедитесь, что вы переименовали находящийся в корневой папке Joomla файл htaccess.txtв .htaccess(если переименовать файл в проводнике Windows не удается, воспользуйтесь интерфейсом командной строки или каким-либо файловым менеджером, например, Total Commander).

Если вы получили сообщение о том, что ваша конфигурация не может быть перезаписана, задайте те же два значения вручную. Для этого откройте файл configuration.phpв корневой папке Joomla, найдите строки:

public $sef = '0'; public $sef_rewrite = '0';

и измените оба значения на " 1" вместо "0".

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

Напишем функцию для генерации SEF-ссылок. Создайте файл /components/com_myquestions/router.php:

Мы создаем пустой массив $segments. Затем проверяем, есть ли в массиве запроса элемент "task", и в этом случае добавляем значение задачи в массив $segments в качестве первого элемента и затем удаляем task из запроса. Далее мы повторяем тот же процесс для id. Наконец, возвращаем массив $segments, чтобы JRoute::_() могла закончить построение URL.

Исправим функции вывода нашего компонента так, чтобы они выводили SEF-ссылки вместо обычных. Откройте файл /components/com_myquestions/myquestions.html.phpи измените код функции showCategories() класса HTML_questions следующим образом:

function showCategories($rows, $option) { ?>

'>

'>

id.'&task=showlist'); echo ''; } ?>

'.$row->name. '

'.$row->desc.'

Измените выделенный код в функции HTML_questions::showQuestions():

foreach($rows as $row) { $link = JRoute::_('index.php?option='.$option.'&id='.$row->id.'&task=showquestion'); $link_cat = JRoute::_('index.php?option='.$option.'&id_cat='.$row->id_cat.'&task=showlist'); ?>

Измените также выделенный код в функции HTML_questions::showQuestion():

function showQuestion($row, $option, $row_cat) { $link_cat = JRoute::_('index.php?option='.$option.'&id_cat='.$row->id_cat.'&task=showlist');

Теперь компонент будет генерировать SEF-ссылки по шаблону, установленному в функции MyQuestionsBuildRoute().

Декодирование SEF-ссылок

Если вы сейчас попытаетесь щелкнуть на одной из SEF-ссылок, то получите сообщение:

"Fatal error: Call to undefined function myquestionsParseRoute() in Y:homelocalhostwwwjoomlaincludesrouter.php on line …".

Напишем функцию для декодирования SEF-ссылок.

Откройте файл /components/com_myquestions/router.phpи добавьте следующую функцию:

function MyQuestionsParseRoute ($segments) { $vars = array(); $vars['task'] = @$segments[0]; $vars['id'] = @$segments[1]; return $vars; }

Как видите, в функции MyQuestionsParseRoute() мы считали переменные task и id из массива $segments в том же порядке, в котором мы их записывали в одноименный массив в функции MyQuestionsBuildRoute().

Знаки "@" при получении элементов массива $segments используются для подавления вывода сообщений об обращении к несуществующим элементам массива, т.к. не все наши SEF-ссылки будут содержать id.

Теперь щелкните по какой-либо ссылке во фронтенде и обратите внимание на строку статуса в браузере. Вы должны увидеть URL вида: ссылка: http://localhost/joomla/component/myquestions/showlistили ссылка: http://localhost/joomla/component/myquestions/showquestion/1

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

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

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

SEF-ссылки в Joomla создаются с помощью метода JRoute::_(), который переводит внутреннюю ссылку, генерируемую Joomla, в SEF-ссылку. Чтобы компонент работал с SEF-ссылками, сгенерированными по собственному шаблону, необходимо создать в корневой папке его фронтенда файл router.php, в котором должны находиться функция для генерации SEF-ссылок и функция для их декодирования. Эти функции осуществляют взаимно обратные операции: первая из них из массива элементов HTTP-запроса создает массив сегментов SEF-ссылки, а вторая из массива сегментов SEF-ссылки создает массив переменных HTTP-запроса.

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

Для работы с документом и с данными пользователя в Joomla существуют соответственно классы JDocument и JUser.

Вопросы

Какой метод переводит внутреннюю ссылку, генерируемую Joomla, в SEF-ссылку?

Каким образом компоненты работают с SEF-ссылками?

Для чего служат функции генерации и декодирования SEF-ссылок?

Что такое шаблон SEF-ссылок и как он задается?

Какие классы используются для работы с документом и с данными пользователя?

Упражнения

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


    Ваша оценка произведения:

Популярные книги за неделю