Я розробляю спеціальний компонент для Joomla! 3.x і хочете здійснити AJAX-дзвінок всередині нього, щоб отримати деякі дані. Який правильний спосіб це зробити?
Я розробляю спеціальний компонент для Joomla! 3.x і хочете здійснити AJAX-дзвінок всередині нього, щоб отримати деякі дані. Який правильний спосіб це зробити?
Відповіді:
ВИМОГАЙТЕ ЗВЕРНІТЬСЯ, ЩО ЦІЙ ВІДПОВІСТЬ вже кілька років і не оновлювався. Не соромтесь редагувати / коментувати, якщо ви вважаєте, що щось більше не є точним.
Дійсно офіційного способу вирішення цього питання майже немає, багато що залежить від складності та того, наскільки ви хочете покластися на схему MVC, щоб виконати роботу.
Нижче наведено декілька можливих рішень, що має працювати в Joomla 2.5 та 3.x. Код поданий не для завдання копіювання, а як загальна ідея.
До Joomla! 3.2. Єдине, що вам потрібно використовувати приклади нижче, - це component
. Після Joomla 3.2 (для нижчих складних завдань) ви можете обробляти запит від модулів та плагінів.
Ваша 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 дивіться нижче, як все поставити в контролер.
Якщо ви зробите свій запит Ajax на субпідрядник , наприклад:
index.php?option=com_similar&controller=abc&format=raw
Чим має бути ваше ім'я субконтролера (для необробленого виду) abc.raw.php
.
Це означає також, що у вас / можуть бути 2 субконтролера на ім'я Abc.
Якщо ви повернете JSON, це може мати сенс використовувати format=json
і abc.json.php
. У Joomla 2.5. У мене були деякі проблеми з тим, як ця опція працювала (якось вихід був пошкоджений), тому я використовував сирий
Якщо вам потрібно створити дійсну відповідь 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=de
).
Нове у Joomla 3.2! - дозволило вам робити запити обробки без створення компонента
Joomla! Інтерфейс Ajax - тепер Joomla забезпечує легкий спосіб обробки запиту Ajax у плагіні або модулі. Ви можете скористатися Joomla! Інтерфейс Ajax, якщо у вас вже немає компонента або якщо вам потрібно робити запити від модуля, який у вас вже є.
JRequest
? Це застаріло, чи просто $this->input
так я використовую v3.x?
JRequest
. Спасибі
Valid JSON Response
розділі.
Це пізня відповідь на це дуже добре відповідне запитання, але я хотів додати це рішення для переслідування для тих, хто потребує простого способу дістатися до даних своїх компонентів за допомогою дзвінка AJAX.
З усіма версіями Joomla, сторонніми можливостями та хаками, які я виявив протягом декількох днів гуглінгу, це був найпростіший підхід, який я міг придумати, - і відгуки виразно оцінені.
execute
до мого існуючого основного контролера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 \ контролери \ 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"
}
}
Відповідь Валентина хороша, але є трохи надмірно складною, якщо все, що вам потрібно зробити, це додати 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
субконтролері
public function keep_alive() {
$this->ajax_check();
//Do your processing and echo out whatever you want to return to the AJAX call
header('HTTP/1.1 202 Accepted', true, 202);
echo 'OK';
JFactory::getApplication()->close();
}
// Verifies jtoken and does a basic check that this is actually an AJAX call
private function ajax_check() {
if(!JSession::checkToken('GET') || !isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') {
header('HTTP/1.1 403 Forbidden', true, 403);
JFactory::getApplication()->close();
}
}
Відповідь Валентина хороша.
Я віддаю перевагу контролеру 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.
JResponseJson
клас для обробки цього?
Якщо ви впевнені на 100%, що немає додаткового плагіна, який додає вихід Javascript, чистий json_encode працює добре.
Але ... наприклад, JomSocial додає "" весь сайт.
Отже ... зручний прийом, оберніть json_encode тегами та обробіть його на стороні Javascript.
echo '@START@' . json_encode(...) . '@END@';
Ви можете отримати доступ до контролера безпосередньо, використовуючи ім'я контролера у завданні:
index.php?option=com_similar&task=controller.abc&format=raw
зателефонує: controller.raw.php (повернення є необробленим)
index.php?option=com_similar&task=controller.abc
зателефонує: controller.php (повернення - HTML, якщо ви не використовуєте die;
)