Каков правильный способ вызова AJAX в компоненте?
Я разрабатываю пользовательский компонент для Joomla! 3.x и хотите сделать вызов AJAX внутри него, чтобы получить некоторые данные. Каков правильный способ сделать это?
6 ответов
ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАТЕЛЬНО, ЧТО ЭТО ОТВЕТ уже несколько лет и не был обновлено. Не стесняйтесь редактировать /комментировать, если вы считаете, что что-то перестает быть точным.
Аннотация
Практически нет официального способа справиться с этим, это многое зависит от сложности и того, как вы хотите полагаться на шаблон MVC для выполнения этой работы.
Ниже приведены некоторые возможные решения, которые должны работать в Joomla 2.5 и 3.x. Код не представлен для задания copy-paste, а скорее как общая идея.
До Joomla! 3.2 единственное, что вам нужно использовать в приведенных ниже примерах - это компонент component
. После Joomla 3.2 (для более сложных задач) вы можете обрабатывать запрос от модулей и плагинов.
Общий ответ HTML (следующий устаревший MVC)
Ваш URL для задачи должен выглядеть следующим образом:
index.php?option=com_similar&task=abc&format=raw
Вместо создания контроллера, который будет использовать представление, скажем Abc
, который будет содержать файл view.raw.html (идентичный нормальному файлу представления).
Ниже приведен код для генерации необработанного ответа HTML:
/controller.php
public function abc()
{
// Set view
// Joomla 2.5
JRequest::setVar('view', 'Abc');
// (use JInput in 3.x)
$this->input->set('view', 'Abc');
parent::display();
}
/views/abc/view.raw.php
<?php
defined('_JEXEC') or die;
jimport('joomla.application.component.view');
class SimilarViewAbc extends JViewLegacy
{
function display($tpl = null)
{
parent::display($tpl);
}
}
/views/abc/tmpl/default.php
<?php
echo "Hello World from /views/abc/tmpl/default.php";
Примечание. Это решение, которое я бы использовал, если бы мне пришлось возвращать HTML (он чище и следует логике Joomla). Для возврата простых данных JSON см. Ниже, как поместить все в контроллер.
Subcontrollers
Если вы сделаете свой запрос Ajax в субконтроллере , например:
index.php?option=com_similar&controller=abc&format=raw
Чем ваше имя субконтроллера (для необработанного представления) должно быть abc.raw.php
.
Это также означает, что у вас /может быть 2 субконтроллера с именем Abc.
Если вы вернете JSON, может иметь смысл использовать format=json
и abc.json.php
. В Joomla 2.5. У меня были некоторые проблемы, когда эта опция работала (как-то результат был поврежден), поэтому я использовал raw.
Действительный ответ JSON (следующий новый /устаревший MVC)
Если вам нужно создать действительный ответ JSON , проверьте страницу документов Генерация Выход JSON
// We assume that the whatver you do was a success.
$response = array("success" => true);
// You can also return something like:
$response = array("success" => false, "error"=> "Could not find ...");
// Get the document object.
$document = JFactory::getDocument();
// Set the MIME type for JSON output.
$document->setMimeEncoding('application/json');
// Change the suggested filename.
JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');
echo json_encode($response);
Обычно вы вводите этот код в контроллер (вы вызовете модель, которая вернет данные, которые вы кодируете, - очень распространенный сценарий). Если вам нужно сделать это дальше, вы также можете создать представление JSON (view.json.php), аналогичное исходному примеру.
Безопасность
Теперь, когда запрос Ajax работает, еще не закрывайте страницу. Читайте ниже.
Не забудьте проверить подделки запросов. JSession::checkToken()
пригодится здесь. Прочтите документацию о том, как добавить CSRF-анти-спуфинг для форм
Многоязычные сайты
Может случиться так, что если вы не отправите имя языка в запросе, Joomla не будет переводить нужные вам строки.
Рассмотрим как можно скорее добавить параметр lang к вашему запросу (например, &lang=de
).
Joomla! Интерфейс Ajax
Новое в Joomla 3.2! - позволяет вам обрабатывать запросы без создания компонента
Joomla! Ajax Interface - Joomla теперь обеспечивает легкий способ обработки запроса Ajax в плагине или модуле. Вы можете использовать Joomla! Ajax Interface, если у вас еще нет компонента или вам нужно сделать запросы от модуля, который у вас уже есть.
Это поздний ответ на этот очень хорошо ответивший вопрос, но я хотел добавить это решение для решения задач для тех, кому просто нужен простой способ получить данные своих компонентов с помощью вызова AJAX.
Со всеми версиями Joomla, возможностями сторонних разработчиков и хаками, которые я нашел за несколько дней работы в Интернете, это был самый простой подход, который я мог придумать, и обратная связь ОПРЕДЕЛЕННО оценена.
- Добавлена функция
execute
к существующему основному контроллеру - Создал субконтроллер с публичной функцией для задач (я), которые я хотел вызвать с помощью AJAX
- Используется встроенный класс Joomla JResponseJson для обработки вывода ( это действительно приятно! )
URL-адрес для вызова /выполнения задачи:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Модифицированный главный контроллер \ com_example \ controller.php
class ExampleController extends JControllerLegacy {
public function display($cachable = false, $urlparams = false) {
$app = JFactory::getApplication();
$view = $app->input->getCmd('view', 'default');
$app->input->set('view', $view);
parent::display($cachable, $urlparams);
return $this;
}
public function execute()
{
// Not technically needed, but a DAMN good idea. See http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms
// JSession::checkToken();
$task = JFactory::getApplication()->input->get('task');
try
{
parent::execute($task);
}
catch(Exception $e)
{
echo new JResponseJson($e);
}
}
}
Новый субконтроллер \ com_example \ controllers \ forajax.php
require_once JPATH_COMPONENT.'/controller.php';
class ExampleControllerForAjax extends ExampleController
{
public function MyTaskName()
{
$app = JFactory::getApplication();
$data['myRequest'] =$_REQUEST;
$data['myFile'] =__FILE__;
$data['myLine'] ='Line '.__LINE__;
$app->enqueueMessage('This part was reached at line ' . __LINE__);
$app->enqueueMessage('Then this part was reached at line ' . __LINE__);
$app->enqueueMessage('Here was a small warning at line ' . __LINE__, 'warning');
$app->enqueueMessage('Here was a big warning at line ' . __LINE__, 'error');
$task_failed = false;
echo new JResponseJson($data, 'My main response message',$task_failed);
$app->close();
}
}
Полученный вывод JSON
{
success: true,
message: "My main response message",
messages: {
message: [
"This part was reached at line 26",
"Then this part was reached at line 27"
],
warning: [
"Here was a small warning at line 28"
],
error: [
"Here was a big warning at line 29"
]
},
data: {
myRequest: {
option: "com_example",
task: "mytaskname",
Itemid: null
},
myFile: "C:\mysite\components\com_example\controllers\forajax.php",
myLine: "Line 24"
}
}
Ответ Valentin хорош, но немного сложнее, если все, что вам нужно сделать, это добавить 1 или 2 вызова ajax к уже созданному компоненту. Совершенно невозможно обойтись без создания отдельных файлов controller.raw.php
или view.raw.php
.
Чтобы сделать этот вызов ajax
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
В подкомплексе
job
Ответ Валентина хорош.
Я предпочитаю json-контроллер, который обрабатывает кодировку и обработку ошибок, для этого я создал базовый класс json:
class itrControllerJson extends JControllerLegacy {
/** @var array the response to the client */
protected $response = array();
public function addResponse($type, $message, $status=200) {
array_push($this->response, array(
'status' => $status,
'type' => $type,
'data' => $message
));
}
/**
* Outputs the response
* @return JControllerLegacy|void
*/
public function display() {
$response = array(
'status' => 200,
'type' => 'multiple',
'count' => count($this->response),
'messages' => $this->response
);
echo json_encode($response);
jexit();
}
}
Этот контроллер расширяется классом контроллера, который выполняет эту работу, примерно так:
require_once __DIR__.'json.php';
class componentControllerAddress extends itrControllerJson {
public function get() {
try {
if (!JSession::checkToken()) {
throw new Exception(JText::_('JINVALID_TOKEN'), 500);
}
$app = JFactory::getApplication();
$id = $app->input->get('id', null, 'uint');
if (is_null($id)) {
throw new Exception('Invalid Parameter', 500);
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*');
$query->from('#__table');
$query->where('id = '.$db->quote($id));
$db->setQuery($query);
$response = $db->loadObject();
$this->addResponse('message', $response, 200);
} catch (Exception $e) {
$this->addResponse('error', $e->getMessage(), 500);
}
$this->display();
}
}
, и вы вызываете запрос следующим образом:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
Хэш-токен генерируется JSession :: getFormToken (). Таким образом, полный полный вызов может выглядеть следующим образом:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Второй параметр имеет значение «false», поэтому мы можем использовать его в javascript-вызовах без перезаписи xml.
Если вы на 100% уверены, что плагин Thrid-Party не добавляет никакого выхода Javascript, чистый json_encode работает нормально.
Но ... например JomSocial добавляет «» ко всему сайту.
Итак ... удобный трюк, оберните json_encode тегами и обработайте его на стороне Javascript.
echo '@[email protected]' . json_encode(...) . '@[email protected]';
Вы можете получить доступ к контроллеру напрямую, используя имя контроллера в задаче:
index.php?option=com_similar&task=controller.abc&format=raw
вызовет: controller.raw.php (return is raw)
index.php?option=com_similar&task=controller.abc
вызывается: controller.php (return is html, если вы не используете die;
)