Каков правильный способ вызова AJAX в компоненте?

Я разрабатываю пользовательский компонент для Joomla! 3.x и хотите сделать вызов AJAX внутри него, чтобы получить некоторые данные. Каков правильный способ сделать это?

39 голосов | спросил Dmitry Rekun 23 AMpWed, 23 Apr 2014 11:43:11 +040043Wednesday 2014, 11:43:11

6 ответов


47
  

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАТЕЛЬНО, ЧТО ЭТО ОТВЕТ уже несколько лет и не был   обновлено. Не стесняйтесь редактировать /комментировать, если вы считаете, что что-то перестает быть точным.

Аннотация

Практически нет официального способа справиться с этим, это многое зависит от сложности и того, как вы хотите полагаться на шаблон 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, если у вас еще нет компонента или вам нужно сделать запросы от модуля, который у вас уже есть.

ответил Valentin Despa 23 AMpWed, 23 Apr 2014 11:57:27 +040057Wednesday 2014, 11:57:27
19

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

Со всеми версиями Joomla, возможностями сторонних разработчиков и хаками, которые я нашел за несколько дней работы в Интернете, это был самый простой подход, который я мог придумать, и обратная связь ОПРЕДЕЛЕННО оценена.

  1. Добавлена ​​функция execute к существующему основному контроллеру
  2. Создал субконтроллер с публичной функцией для задач (я), которые я хотел вызвать с помощью AJAX
  3. Используется встроенный класс 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"
    }
}
ответил GDP 9 J000000Wednesday14 2014, 21:14:40
11

Ответ 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
ответил Spunkie 23 PMpWed, 23 Apr 2014 21:25:20 +040025Wednesday 2014, 21:25:20
7

Ответ Валентина хорош.

Я предпочитаю 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.

ответил Harald Leithner 23 PMpWed, 23 Apr 2014 12:46:33 +040046Wednesday 2014, 12:46:33
4

Если вы на 100% уверены, что плагин Thrid-Party не добавляет никакого выхода Javascript, чистый json_encode работает нормально.

Но ... например JomSocial добавляет «» ко всему сайту.

Итак ... удобный трюк, оберните json_encode тегами и обработайте его на стороне Javascript.

echo '@[email protected]' . json_encode(...) . '@[email protected]';
ответил Anibal 24 AMpThu, 24 Apr 2014 01:12:10 +040012Thursday 2014, 01:12:10
2

Вы можете получить доступ к контроллеру напрямую, используя имя контроллера в задаче:

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

ответил Dennis Heiden 9 Maypm16 2016, 17:12:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132