GrAndSE’s blog

Думки, думки і ще раз думки

AJAX та Joomla!

Доволі популярною CMS є Joomla!. На жаль, в ній відсутній інструментарій для роботи з AJAX. А в деяких випадках присутність AJAX може додати динаміки вашому проекту, зменшити навантаження на сервер та канал зв’язку. Ось і передімною постало завдання додати деякі елементи на сайт, які б працювали через AJAX.

Муркуючи чим скористатися як клієнтською частиною, я розмірковував стосовно доцільності використання jsHttpRequest, JQuery. Однак прийшов до висновку, що мені буде достятньо функціоналу власноруч написаного JavaScript про який мова йшла не так давно.

Чого не вистачає Joomla!

Скажу одразу, що раніше я працював лише з версією Джумли близькою до 1.0. Точно не згадаю, оскільки з тих часів минув вже рік. А цього разу було вирішено скористатись версією 1.5. І враження від неї досить спірні.

З одного боку, крок в перед. ООП використовується, спроба наблизитись до стандартів і використовувати MVC патерн проектування.

З іншого боку, величезні зміни відносно попередніх версій, ієрархія стандартних класів занадто громіздка, система написання компонентів до системи як на мене надлишкова. Ну посудіть самі: в директорії компоненту є клас-контролер, піддерикторія для моделі, в який зазвичай лежить клас-модель та додатковий клас для функцій, що використовуються в моделі, сама модель звертається чорт його знає куди, а саме до бібліотеки стандартних класів, звідки бере якогось нащадка від JTable (якщо я не помиляюсь), який відповідає за зв’язок з базою данних, а ще залишається частина, що відповідає за відображення.. і містить вона в собі массу піддиректорій, кожна з яких містить клас-опис відображення, та піддиректорію з шаблонами. Що небудь зрозуміли? Я сам до кінця всю цю схему не можу зрозуміти, хоча воюю з нею майже тиждень. Для опису того, що я зміг знайти і в чому розібрався потрібно писати окрему серію заміток :)

Не злякались? Тоді йдемо далі.

Для того, щоб в результаті виконання запиту повертались лише необхідні нам дані, ми мусимо повертати результати виконання лише одного компоненту, чи то завантажувати лише один модуль. І якщо в першому випадку є добре реалізовані функції, які тільки потрібно найти, то в другому випадку елегантного виходу, що не потребував би дописування власних функцій я не знайшов.

Ну і звісно не має в джумлі підготовленого спеціально для оновлення одного елементу сценарію.

Вирішуючи проблеми

Раніше були чудові функції mosLoadModule та mosLoadComponent, що виконували код модуля та компонента. Тепер вони також існують, однак повертають рядок у вигляді <jdoc:include type=”module” name=”module_name” />, який потім має парситись шаблонізатором під час обробки усього шаблону. Як примусово опрацювати цей рядок, щоб повертався одразу html я не зміг зрозуміти. До того ж це зайва робота – парсити цей рядок. Тому я вирішив написати власну функцію завантаження окремого джумлівського модуля:

<code>function loadModule($name) {
global $mainframe, $option;

if (empty($name)) {
// Throw 404 if no module

JError::raiseError(404, JText::_(“Module Not Found”));
return;
}

$scope = $mainframe->scope; //record the scope
$mainframe->scope = $name; //set scope to modules name

// Build the module path
$name = preg_replace(‘/[^A-Z0-9_\.-]/i’, ”, $name);

// Define component path
define( ‘JPATH_MODULE’, JPATH_BASE.DS.’modules’.DS.$name);
define( ‘JPATH_MODULE_SITE’, JPATH_SITE.DS.’modules’.DS.$name);
define( ‘JPATH_MODULE_ADMINISTRATOR’, JPATH_ADMINISTRATOR.DS.’modules’.DS.$name);

// get module path
if ( $mainframe->isAdmin() && file_exists(JPATH_COMPONENT.DS.’admin.’.$name.’.php’) ) {
$path = JPATH_MODULE.DS.’admin.’.$name.’.php’;

} else {
$path = JPATH_MODULE.DS.$name.’.php’;
}

// Execute the module
ob_start();
require_once $path;
$contents = ob_get_contents();
ob_end_clean();

return $contents;
}</code>

За основу взято функцію, що завантажує код компонента, однак відкинуто зайві перевірки зі зверненням до бази даних – трішки не по джумлівськи, однак AJAX має не лише додавати легкості користування системою, а також і розвантажувати сервер від зайвих запитів.

Доречі, для коректної роботи цієї функції необхідно підключити один додатковий файл, який чомусь самостійно не підключається:

require_once ( JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'application' . DS . 'module' . DS . 'helper.php');

Тепер час попрацювати над обробкою запитів до серверу. Щоб не змінювати код мого javascript для роботи з AJAX, я вирішив його назвати.. ajaxindex.php :) . За основу взято звичайний index.php з Joomla 1.5.2. Перерахую ряд змін, необхідних для того, щоб все працювало як слід.

Замiсть
$mainframe->render();
необхідно вписати:
$module = JRequest::getVar('module', false);
$content['responseText'] = ($module)? loadModule($module): JComponentHelper::renderComponent($component);

Таким чином ми відключаємо парсинг всього шаблону, а виконуємо завантаження модуля чи компонента. Посилання на завантаження модуля матиме вигляд ajaxindex.php?module=module_name. Для компонента воно буде аналогічним для звичайних “компонентних” посилань Joomla 1.5.

Нагадаю, що мій dsajax.js очікую на відповідь у форматі JSON. Тому необхідно замінити
echo JResponse::toString($mainframe->getCfg('gzip'));
на кодування.
echo json_encode($content);

Ну і ще я дописав раніше описану функцію на початок ajaxindex.php, не забувши додати вказаний мною рядок підключення бібліотеки функцій Joomla для роботи з модулями.

Залишається розмістити сам файл dsajax.php де Вам здається зручним, та вписати його підключення в сам шаблон, яким ви користуєтесь. Тепер ви маєте можливість скористатись деградабельним аяксом в Joomla.

Робимо висновки

Гадаю, що така реалізація має повне право на життя. Працює вона досить стабільно, дає досить широкі можливості без великої кількості додаткового коду. Однак мені здається, що подібна система ще не є ідеальною. Наприклад, розмірковую стосовно доцільності в залишених мною у спокої рядках з index.php, що генерують події, та систему ініціалізації. Гадаю, що можна ще зменшити навантаження на сервер шляхом спрощення цієї системи. Хотілося б почути думки з цього приводу, оцінки людей. Можливо хтось знайде недоліки, чи кращий метод.

Серпень 13, 2008 - Опубліковано grandse | Програмування | , , , , | 2 Коментарі/ів

2 Коментарі/ів »

  1. Пошукайте на joomlaforum.ru розробку si-rus. Там вона є адаптована під джумлу, хоча його лібу можна куди-небудь прикрутити. Його офф.сайт – fullajax.ru.

    Comment by yAnTar | Вересень 30, 2008 | Відповісти

  2. Дякую за посилання. Гарненька бібліотечка. Фактично, я написав щось рподібне, однак у FullAjax функціонал ширший.
    Поки що мені не вдається розібратись, як це буде працювати з Joomla без аналога того, що я дописав для самої Joomla! Тобто скомпонувавши мої зміни в Joomla з бібліотекою можна отримати систему з потужним функціоналом та AJAX.

    Comment by grandse | Вересень 30, 2008 | Відповісти


Залишити коментар