tushov.ru

блог php-программиста, преподавателя и конcультанта

Joomla, PHP

Реализация AJAX-модулей в Joomla 1.5

В Joomla 1.5.x AJAX-запросы внутри компонентов можно посылать через специальный файл index2.php — отличие которого от стандартного состоит в том что он не загружает шаблон Joomla, а только выводит содиржимое сгенерированное непосредственно компонентом. Т.е. к примеру запрос вида http://ваш_сайт/index2.php?option=com_frontpage — покажет на странице «чистый» вывод компонента com_frontpage. Такого  рода запросы очень удобны при реализации AJAX-вызовов в компонентах. Однако маршрута вызова исполнения и вывода конкретного модуля в Joomla увы не предусмотрено. На данный момент есть различные методы реализации AJAX-вызовов модулей в Joomla как правило за счет специальных плагинов или компонент обрабатывающие AJAX-запросы. На мой взгляд модуль  должен быть самодостаточным (автономным) и по возможности не требовать установки каких-либо компонент или плагинов реализующих проброс AJAX-запросов к нему. Для того чтобы не терять возможности API Jooml’ы и не городить каждый раз какой-то особый функционал для AJAX-модулей, я сделал простое решение для себя:
в своих модулях в которых используются AJAX-вызовы я просто использую сделанный мной файл ajax.php, следующего содержания:

все AJAX-запросы идут как раз таки на этот файл ajax.php, лежащий внутри папки модуля.
а уже обработкой AJAX-запросов и ответов занимается сам файл модуля. Таким образом создавая очередной модуль использующий AJAX я просто кидаю в папку с ним этот файл ajax.php и делаю что хочу внутри этого модуля.
Таким образом сохраняется автономность самого модуля, при этом вам не надо править что-то в файле ajax.php, он одинаковый для всех таких модулей — просто положите его в папку с модулем и посылайте AJAX-запросы через него!

Пример модуля реализованного по вышеописанной технологии.

60 Comments

  1. Макс

    Друг помоги пожалуйста советом а то чото модуль не работает… пишет ошибку:
    »
    Warning: require_once(W:\home\saitostroi\www\modules\mod_login\ajax.php\includes\defines.php) [function.require-once]: failed to open stream: No such file or directory in W:\home\saitostroi\www\modules\mod_login\ajax.php on line 10

    Fatal error: require_once() [function.require]: Failed opening required ‘W:\home\saitostroi\www\modules\mod_login\ajax.php\includes\defines.php’ (include_path=’.;/usr/local/php5/PEAR’) in W:\home\saitostroi\www\modules\mod_login\ajax.php on line 10
    » , а если прописать относительные пути к файлам в папке include , пишит ошибку не найден файл конфигурации и exit;

    подскажи пожалуйста … честное спасибо ! =)

  2. Макс

    с одним модулем разобрался…все работает если модуль несложной структуры как на 1,5 а по типу от первой джумлы… только еще вот косяк остался небольшой … в ИЕ все нормально отображается….а Firefox выдает хтмл как текст…

  3. Макс

    =)))) вопрос решен… автару честное спасибо и желаю ему крепкого здоровья для свершения всех Добрых дел и успехов во всех Добрых делах !!! =)))

  4. Тушов Леонид

    спасибо! рад что у вас все получилось =)

  5. Макс

    Уважаемый Друг! а вы смогли бы подсказать подобное решение для реализации ajax вызова плагинов CB в Джумле… по сути думаю было бы очень хорошо если бы табы в CB работали на аяксе… а то если подключать много плагинов к СВ (форумы галлереи блоги каталоги итп) создаются много запросов при открытии профиля пользователя… а с аяксом было бы гораздо проще.. реализация табов у меня есть готовая нехватает пока решения как обращаться к плагинам CB чтобы они по типу этого решения с модулями могли работать автономно… спасибо за внимание =)

  6. Тушов Леонид

    увы я ни разу не писал плагинов к вами упомянутому СВ, потому совсем не представляю как там все устроено (а именно модули и т.д. и т.п.). Предложенная мною реализация AJAX вызовов моделей Joomla может быть как угодно использована вами по вашему усмотрению!

  7. Спасибо! Очень помог ваш пример)

  8. Уважаемый Леонид, не могли бы Вы выложить любой модуль из тех, где реализована данная техника?
    Хочу сделать модуль-слайдер ньюзов из ком_контент (вроде этого). Сперва «пошёл лесом», т.е. делал отдельный компонент. Если бы удалось разобрацо в вышеописаной технике, был бы очень признателен.
    Спасибо.

  9. Тушов Леонид

    вот пример модуля http://tushov.ru/wp-content/uploads/2010/08/mod_newscount.zip, AJAX реализован на основе jQuery. Думаю принцип построения такого рода модулей вы поймете посмотрев на этот пример.

  10. Спасибо!

  11. Хороший пример, спасибо.

    только у вас ошибка в mod_newscount.xml

    дублируется строка [php]<filename module="mod_newscount">mod_newscount.php</filename>[/php]

    Из-за чего модуль отказывается устанавливаться — говорит что уже есть такой файл

    И неплохо бы положить в модуль jQuery, а то у неопытного человека ничего не получится. плюнет и пойдет дальше искать варианты модулей с AJAX

    спасибо за внимание

  12. Тушов Леонид

    исправил ошибку дублежа строки…
    добавил подключение JQuery:
    [php]<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>%5B/php%5D
    только господа тестирующие будьте осторожны в случае если у вас уже подключена библиотека jQuery или же подключена mootols могут быть проблемы.

  13. Макс

    Уважаемый друг, Леонид! если вас не затруднит продолжение этой темы, окажите любезность прокоментировав решение noconflict для совместного использования jquery и mootools =)

  14. Тушов Леонид

    почитайте тут http://www.htmlblog.ru/web-development/using-jquery-mootools-na-odnoj-stranice.html
    или просто поищите информацию на тему «jquery и mootools» — как правило проблема кроется в обоюдном использовании обеими библиотеками вызова вида $()

  15. Макс

    Леонид спасибо! вы снова на высоте! спасибо спасибо спасибо за вашу информационную поддержку ! =))

  16. Любопытное решение, а как насчет безопасности?

  17. Тушов Леонид

    Любопытное решение, а как насчет безопасности?

    уже третий раз слышу подобного типа вопрос..
    и хочется сразу задать встречный вопрос: А в чем проблема? Где уязвимость?
    Ваше беспокойство о безопасности должно быть как то и чем-то подкреплено? иначе это просто болезнь незакрытых дверей..
    уважаемые!!! Прошу вас, давай-те будем более конструктивны в таких вопросах.
    Если чувствуете что здесь есть проблемы с безопасностью — опишите свои страхи и мысли формально, аргументируйте что где и как может быть взломано и прочее — иначе я сочту просто за ничем не подкрепленные страхи…

  18. Добрый день, реализовал свой модуль на основе вашего примера, все работало отлично пока я не попытался включить, установленный seo url, в месте модуля подгружается вся страница целиком, не подскажите в чем может быть проблема?

  19. Тушов Леонид

    как выглядит ваш URL к AJAX ?
    и через JRoute::_

  20. Дмитрий

    Подскажите пожалуйста, как отправить скрипту ajax.php несколько параметров. Делаю так [php]JRoute::_(‘modules/mod_newscount/ajax.php?category_id=1&addmod_id=1’);[/php], но это не появляется ошибка «invalid assignment left-hand side».

  21. Тушов Леонид

    так вроде все просто, это же обычный GET запрос в URL’е, к примеру
    [php]<script>
    $(‘#newscount’).load(‘<?php echo JRoute::_(‘/modules/mod_newscount/ajax.php?data=1&param1=value1&param2=value2&param3=value3′); ?>’);
    </script>[/php]
    можете еще посмотреть справку по методу load в JQuery: http://api.jquery.com/load/ — просто там есть другой способ передачи GET-переменных в примерах увидите

  22. Макс

    Спасибо за решение, вопрос:
    в загружаемом модуле не преобразуются ссылки в SEF через JRoute
    Думаю нужно что-то подключить, не знаю что.
    В таком же модуле без AJAX — всё как нужно, преобразуются ссылки в SEF

  23. Ирина

    Леонид, большое спасибо за решение — благодаря вам удалось сэкономить время, уже собиралась писать сама и вдруг наткнулась на ваш блог

  24. Ирина

    Снова я) Маленький вопрос:
    Почему в строчке header(«Content-type: text/plain; charset=utf-8»); вы поставили text/plain, а не text/html, к примеру? Пожалуйста, поясните, с чем это связано
    Дело в том, что если использовать отображение модуля в iframe, то с text/plain, соотвественно, выводятся теги как текст
    P.S: сейчас думаю, как изменить скрипт, чтобы из модуля правильно получался результат Juri::base() (дело в том, что при вызове модуля таким образом Juri::base() возвращает не http(s)://мой-сайт.ххх/, а http(s)://мой-сайт.ххх/modules/mod_мой-модуль/ . Естественно, поэтому же и с JRoute таже история)

  25. Тушов Леонид

    P.S: сейчас думаю, как изменить скрипт, чтобы из модуля правильно получался результат Juri::base() (дело в том, что при вызове модуля таким образом Juri::base() возвращает не http(s)://мой-сайт.ххх/, а http(s)://мой-сайт.ххх/modules/mod_мой-модуль/ . Естественно, поэтому же и с JRoute таже история)

    используйте:
    [php]JURI::root();[/php]
    http://docs.joomla.org/JURI
    использую так:

    header(«Content-type: text/plain; charset=utf-8»);

    потому что AJAX-запросы делаю с помощью JQuery, получаю в AJAX-запросе ответ — и вставляю полученный HTML с помощью того же JQuery куда мне надо или же делаю с полученными данными что-то…
    кстати на habrahabr.ru мой метод AJAX-вызовов забраковали, сказали что неправильно это нарушает архитектуру Joomla ) Ведь я по сути почти скопировал index.php ) сделал вторую точку входа в Joomla Core. Особой правда опасности кроме как для архитектуры API Joomla я не вижу…

  26. Ирина

    Леонид, спасибо за быстрый ответ!
    Насчет JURI::root() — ситуация в точности та же. Смотрите: в joomla/environtment/uri.php функция все равно получает путь через JURI::base():
    $uri =& JURI::getInstance(JURI::base());
    Результат, соответственно, тот же
    А сам JURI при инициализации получает путь из $_SERVER[‘REQUEST_URI’]

    В общем, это совсем не насущный вопрос — просто захотелось «довести до совершенства»

    P.S:
    Почему забраковали на хабре? Был какой-нибудь дельный аргумент или просто синдром выходных (малолетние снобы)? Реализация мне чем и понравилась, что сделано практически точно по структуре вызовов джумлы.. опасности я и вправду не вижу, другое дело, может всплыть что-то еще вроде Jroute, juri::base

  27. Тушов Леонид

    да с
    [php]JURI::root()[/php]
    я поторопился с ответом ). наверное красоты не получится через API Joomla =) в таком случае ведь по сути мы ушли от головного index.php лежащего в корне сайта (домена) и дающего верный ответ на метод root();
    Вот как раз скорее всего именно по причине копирования содержимого входной точки Jooml’ы (index.php -файла) на хабре и забраковали ) не связалось с их религией такое решение =)
    Если так разобраться — что есть модуль в Joomlа — не более чем блок html-кода выводимый в определенном месте на странице, а я своим решением дал этому блоку управление :) где то в глубине души понимаю что не правильно все это конечно — противоречит использованию модулей ) однако тяга мысли об автономности модуля перевесила.

  28. Ирина

    Да, я тоже пока не вижу красивого решения с JURI и JRoute, но в конкретных задачах эта проблема легко обходится

    где то в глубине души понимаю что не правильно все это конечно – противоречит использованию модулей

    Почему неправильно? Все зависит от конкретной задачи. Мне понадобилось реализовать работу с аяксом в модуле. Товарищи с хабра наверняка сказали бы — напишите компонент и обращайте аякс-вызовы к нему), но, мне кажется, ради нескольких строчек это лишнее
    Добавила ваш блог в закладки :) Спасибо, вы молодец!

  29. Эдуард

    Леонид здравствуйте! извите немного не в тему, и все таки зная вас как Мастера и Профессионала надеюсь не откажете подсказать как в своем компоненте или модуле использовать api джумлы для вывода стандартных сообщений… к примеру как вызвать и показать пользователю alert-message в модуле … спасибо!

  30. Эдуард

    в модуле jdoc:include type=»message» … я имею в виду стандартные сообщения об ошибках или уведомления джумлы… все таки извините за повторную месагу… и еще раз спасибо!

  31. Тушов Леонид

    все достаточно просто в принципе:
    [php]
    $appl =& JFactory::getApplication();
    $appl->enqueueMessage(‘Ваше сообщение’, ‘message’);
    [/php]

  32. Эдуард

    увы не показывает сообщение… я пробовал еще вот таким способом как в стандартном контролере com_user : [php] $link = ‘index.php…итп’; $msg = JText::_(‘Thank you for your e-mail’);
    $this->setRedirect($link, $msg, ‘error’);[/php] и вообще в таком случае прерывается програма и выдает 500 ошибку …

  33. Эдуард

    Леонид, если вы не против может отдельным кратким постом опубликуете решение ? к примеру » joomla 1.5 системные сообщения » а то сколько гуглил ничего реального в этой теме еще ненагуглил =)

  34. [php]
    global $mainframe;
    $msg = ‘текст сообщения!’;
    $mainframe->redirect(‘index.php?option=…………………………………’);
    [/php]

  35. [php]
    global $mainframe;
    $msg = ‘текст сообщения!’;
    $mainframe->redirect(‘index.php?option=…………………………………’, $msg);
    [/php]

  36. Эдуард

    спасибо с майнфрейм чотко работает!!! вот это здорово!!! уважаемые друзья Леонид и denver: позвольте выразить вам благодарность на своем сайте =) размещу ссылку адрес сайта Леонида и если не ошибаюсь адрес товарища denver: denvera.net … еще раз Спасибо Друзья!!! хороших вам настроений и крепкого здоровья для творческих успехов во всех добрых делах! =)

  37. получилось ли решить проблему с тем что Juri::base() выдает http(s)://мой-сайт.ххх/modules/mod_мой-модуль/ ? у меня точно такая же проблема Juri::root() выдает тоже самое

  38. Тушов Леонид

    получилось ли решить проблему с тем что Juri::base() выдает http(s)://мой-сайт

    это и не проблема ведь вовсе, мы же вызов делаем ajax.php лежащего не в корне сайта, потому вообщем-то все нормально
    что касается решения — оно может быть самым простым:
    [php]$rootURL = ‘http://’ . parse_url(Juri::base(), PHP_URL_HOST);[/php]

  39. Shankara

    В вашем примере модуля

    Пример модуля реализованного по вышеописанной технологии.

    в теме «Реализация AJAX-модулей в Joomla 1.5» есть подключение скрипта jquery.
    У меня такой вопрос к вам Леонид: а если на сайте уже есть подключенный скрипт jquery, то загружать из модуля уже не нужно, но как сделать тогда рабочим код?
    Я комментирую строку http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js но тогда модуль не работает. Как сделать чтобы код заработал?

    [php]<?php
    // no direct access
    defined( ‘_JEXEC’ ) or die( ‘Restricted access’ );

    if (JRequest::getVar(‘data’)) {
    $db =& JFactory::getDBO();
    $db->setQuery("SELECT COUNT(*) FROM jos_content");
    $total = $db->loadResult();
    $db->setQuery("SELECT COUNT(*) FROM jos_content WHERE TO_DAYS(created) = TO_DAYS(NOW())");
    $today = $db->loadResult();
    echo "Новостей: $total, за сегодня: " . (int) $today;
    }
    else { ?>
    <!—<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot; type="text/javascript">jQuery.noConflict();</script>—>

    <div id="newscount"></div>
    <script>
    $(‘#newscount’).load(‘<?php echo JRoute::_(‘/modules/mod_newscount/ajax.php?data=1′); ?>’);
    setInterval( function() {
    $(‘#newscount’).load(‘<?php echo JRoute::_(‘/modules/mod_newscount/ajax.php?data=1′); ?>’);
    } , <?php echo $params->get(‘timeout’) * 1000; ?>)
    </script>
    <?php } ?>[/php]

  40. Тушов Леонид

    У меня такой вопрос к вам Леонид: а если на сайте уже есть подключенный скрипт jquery, то загружать из модуля уже не нужно, но как сделать тогда рабочим код?
    Я комментирую строку http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js но тогда модуль не работает. Как сделать чтобы код заработал?

    вам нужно проверять подключен (инициализирован) ли jQuery уже ранее, если не подключен подключать его. Погуглите на тему проверки подлючения jQuery (динамическjt подключение jQuery)

  41. solarscape

    Спасибо.

  42. ASPI

    Спасибо большое! Очень полезная штука, помогла решить вопрос вызова модуля.

  43. Данил

    Спасибо за пример AJAX-модуля.
    Вопрос: как разместить на странице несколько одинаковых модулей, чтобы для каждого загружалось свое содержимое. Например, необходимо два rss-модуля, первый модуль берет новости с одного сайта, второй с другого.

  44. Тушов Леонид

    Например, необходимо два rss-модуля, первый модуль берет новости с одного сайта, второй с другого.

    странный вопрос однако ) все зависит от модуля конкретного. Самое банальная мысль это создать два однотипных модуля (например какой нить RSS-агрегатор), задать им соотв. разные настройки и все.

  45. Андрей

    А в версии Joomla 2.5 будет работать?

  46. Артем

    А в версии Joomla 2.5 будет работать?

    Нет не будет скорей всего, на 99% уверен. Тут потребуется переписать код для подключения фрэймфока. Вообще и в 1.5. и в 2.5 при реализации AJAX я иду следующим путем: Создаю для этого модуля в компоненте на который он логически завязан свой VIEW, ну или для этих целей можно создать свой компонент. Главная идея: у компонента можно получить по ссылке выход только этого компонента без добавления шаблона и тегов html. Для этого в папке компонента VIEW/наш_вид создаем файл view.ajax.php внем впринципе все так же как и в обычном, если надо можно переопределить заголовки http для xml иди JSON, чтобы обратиться к нему из вашего яваскипта в параметрах строки браузера надо указать переменную format=ajax. Вот и вся логика и никаких хаков не надо.

  47. Андрей

    в 2.5 при реализации AJAX я иду следующим путем: Создаю для этого модуля в компоненте на который он логически завязан свой VIEW

    если я правильно понял, это можно и в 1.5 сделать? без хака описанного в данной статье?

  48. Тушов Леонид

    если я правильно понял, это можно и в 1.5 сделать? без хака описанного в данной статье?

    конечно можно не использовать мой метод )
    хотя я всегда удивлялся почему его называют хаком )) Это не хак, а создание экземпляра приложения в стиле API Joomla — на оффсайт есть статья об этом.
    Делал я это для того чтобы не писать специальный компонент-роутер для такого рода модулей получая при этом зависимость модулей от компонента.
    Joomla 2.5.x — горе от ума, понятно что ничего хорошего вообщем-то из бесплатного нет, но что они творят…

  49. Kerch

    Автор, выручай! Как заставить модуль работать под 1.7 ?!
    Rод для подключения фрэймфока проверил. Воде отличий нету.
    Но модуль не работает. Проверил на 1.5 — все ок. Но очень надо под 1.7
    На основе этого модуля планирую написать свой.

    • Тушов Леонид

      Автор, выручай! Как заставить модуль работать под 1.7 ?!
      Rод для подключения фрэймфока проверил. Воде отличий нету.
      Но модуль не работает. Проверил на 1.5 — все ок. Но очень надо под 1.7
      На основе этого модуля планирую написать свой.

      AJAX-запрос проверяли? Уходит он или нет? Что в ответ… Стандартные программистские дела ведь…

  50. korolariya

    удивительная магия=) подскажите как сделать так же только с компонентой=) пытаюсь модуль переделать к меня не особо выходит наверное нужно что то подключать я не знаю как, класно было бы чтобы был пример компоненты с аджакс, например com_hello

  51. Тушов Леонид

    удивительная магия=) подскажите как сделать так же только с компонентой=) пытаюсь модуль переделать к меня не особо выходит наверное нужно что то подключать я не знаю как, класно было бы чтобы был пример компоненты с аджакс, например com_hello

    странный однако у вас вопрос, не содержащий ни какой конкретики о том, что именно у вас не получается на каком именно этапе, о какой версии Joomla идет речь ну и т.д.
    Примерная логика работы компонента использующего AJAX-запросы:
    1) С помощью MooTools или JQuery производится AJAX-запрос к компоненту (как правило вызов определенного метода его контролера)
    2) Метод что-либо возвращает
    3) Получив ответ на запрос, происходит к примеру вывод полученного содержимого внутри какого-нибудь элемента ну и .п.

  52. Xchesh

    Т.е. по-идее я могу сколько угодно и каких угодно параметров передавать и при этом ajax.php абсолютно не меняется? передам : ajax.php?data=1&time=2&second=45
    Получу параметры в mod_namemonule.php с помощью: JRequest::getVar(‘data’); JRequest::getVar(‘time’); JRequest::getVar(‘second’)????
    Я верно понимаю логику? Заполнение полученных данных лежит на JS?

  53. Xchesh

    Сразу не заметил. Jquery .load() отправляет асинхронный запрос с параметрами в ajax.php и загружает полученный контент в указанный элемент.
    Будем пробовать.

  54. Xchesh

    Все реально работает.
    Главное не забыть(как я) в *.xml файл модуля добавить ajax.php.

  55. sonick

    а в 2.5 будет работать?)

  56. xchesh

    а в 2.5 будет работать?)

    Будет. Я запускал именно под 2.5, главное смотри, что JS скриптом отправляешь.

  57. korolariya

    В принципе уже давно разгрёб эту тему с ajax но вот беда новая joomla 2.5 ++ не содержит файлов index2.php и тп. пока ищу как решить эту задачку. Чесно говоря думал эта тема мертвая поэтому сюда больше не заходил, крайне был удивлен увидев что на мой коммент есть ответ=)

    • Тушов Леонид

      В принципе уже давно разгрёб эту тему с ajax но вот беда новая joomla 2.5 ++ не содержит файлов index2.php и тп. пока ищу как решить эту задачку.

      Смысл файла index2.php был лишь в строке:
      [php]$_REQUEST[‘tmpl’] = ‘component’;[/php]
      таким образом вы подключаете шаблон который не грузит ничего лишнего кроме вывода вашего компонента
      Для Joomla 1.6.х и выше в том числе 2.5.х можно просто посылать запросы на index.php но дописывать в URL’е ту же самую переменную &tmpl=component

  58. kerch

    Xchesh, а может поделитесь екземплом какого-то порстенького модуля под 2.5?

Leave a Reply

Theme by Anders Norén