Общая информация

Класс JResponseJson появился в CMS версии 3.x. Он предоставляет общий интерфейс для переменных ответа (например, на Ajax запросы). Класс расположен в директории /libraries/cms/response.

В основном он используется в контроллерах компонентов и дает следующие преимущества:

  • Используя флаг success, JavaScript код (Mootools JRequest.JSON или jQuery.getJSON) может проверить, удачно ли завершилась задача. Если запрос неудачен, может быть использовано событие ошибки JavaScript API.
  • Данные (если есть) будут доступны в свойстве data в виде JSON-объекта
  • Дополнительно можно установить сообщение ответа через свойство message.
  • Все собранные сообщения очереди JApplication будут автоматически направлены в свойство messages.

Еде одним преимуществом является то, что больше нет надобности в закрытии приложения ($app->close()), если Ajax запрос был сделан с помощью format=json. За вас это сделает существующее API.

Как использовать

Наиболее распространённый случай

Рассмотрим пример контроллера:

class MyController extends JControllerLegacy
{
    public function someTask()
    {
        try
        {
            $app = JFactory::getApplication();

            $anyParam = $this->input->get('anyparam');
 
            $result = $this->getModel('example')->createSomething($anyParam);
 
            echo new JResponseJson($result);

            $app->close();
        }
        catch(Exception $e)
        {
            echo new JResponseJson($e);

            $app->close();
        }
    }
}

 


Здесь возвращаемое значение $result просто передается в новый объект JResponseJson и выводится с помощью echo. Это автоматически создает строку в формате JSON:

{"success":true,"message":null,"messages":null,"data":
{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}



В data вы можете передавать массив, объект или значение, при этом флаг success будет автоматически установлен в true.

В нашем случае, если случится какое-то исключение в модели, то оно просто передается напрямую в объект JResponseJson, что приведет к следующим выходным данным:

{"success":false,"message":"Это сообщение исключения","messages":null,"data":null}


 
Так как это исключение, флаг success был автоматически установлен в false, и сообщение исключения стало основным сообщением ответа.

Дополнительные опции

Если первым аргументом конструктора объекта JResponseJson передается не исключение, то вы можете указать произвольное основное сообщение ответа, передавая его вторым аргументом $message:

echo new JResponseJson($result, JText::_('COM_COMPONENT_MY_TASK_SUCCESS'));




Это создаст следующее:

{"success":true,"message":"Запрос завершен успешно.","messages":null,"data":
{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}



Вы можете вручную установить флаг ошибки в false с помощью третьего аргумента $error:

echo new JResponseJson($result, JText::_('COM_COMPONENT_MY_TASK_ERROR'), true);



Вот что мы получим на выходе:

{"success":false,"message":"Произошлаошибка.","messages":null,"data":
{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}


Обратите внимание на то, что таким образом вы можете передать назад данные.

Независимо от того, был ли ответ с ошибкой или удачным, класс JResponseJson отправляет все сообщения обратно клиенту, где они собираются в объекте приложения:

$app = JFactory::getApplication();
 
//Какой-то код ($result = ...)
 
$app->enqueueMessage('Эта часть выполнена успешна');
 
// Еще код
 
$app->enqueueMessage('А здесь было предупреждение','warning');
 
echo new JResponseJson($result, 'Главное сообщение ответа');




Вот как будет выглядеть ответ:

{"success":true,"message":"Главное сообщение ответа","messages":"<<все сообщения приложения>>","data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}


Преимущество такого подхода вы увидите ниже в разделе JavaScript.

Если же вы не хотите посылать назад сообщения, просто установите четвертый аргумент $ignoreMessages конструктора в значение true.

Соответствующий JavaScript код

Ниже приведены примеры JavaScript кода, который может быть использован на клиентской стороне вместе с JResponseJson на стороне сервера.

Пример на MooTools

var req = new Request.JSON({
    method: 'post',
    url: 'index.php?option=com_component&task=mycontroller.someTask&format=json',
    onSuccess: function(r)
    {
        if (!r.success && r.message)
        {
            // Флаг успеха установлен в 'false' и есть основное сообщение ответа. 
            // Вы можете вывести его в alert или в HTML элемент.
            alert(r.message);
        }
        if (r.messages)
        {
            // Все сообщения очереди объекта приложения могут быть выведены с помощью 
            // соответствующей функции Joomla API. Они автоматически отобразятся 
            // в секции messages шаблона.
            Joomla.renderMessages(r.messages);
        }
        if (r.data)
        {
            // Получаем доступ к данным вашего ответа
            alert(r.data.myfirstcustomparam);
            alert(r.data.mysecondcustomparam);
        }
    }.bind(this),
    onFailure: function(xhr)
    {
        // Ajax запрос был неуспешен. JResponseJson не вызван. 
        alert('Ошибка Ajax запроса!');
    }.bind(this),
    onError: function(text, error)
    {
        // Получен ответ от сервера, но это не валидные JSON данные
        // (иногда такое случается при ошибках PHP во время запроса).
        alert(error + "\n\n" + text);
    }.bind(this)
});
req.post('anyparam=myvalue');



Пример на jQuery

$.getJSON('index.php?option=com_component&task=mycontroller.someTask&format=json', {
    data: data
})
.done(function(r) {
    if (!r.success && r.message)
    {
        alert(r.message);
    }
    if (r.messages)
    {
        Joomla.renderMessages(r.messages);
    }
    if (r.data)
    {
        alert(r.data.myfirstcustomparam);
        alert(r.data.mysecondcustomparam);
    }
})
.fail(function() {
    alert('Ошибка Ajax запроса!');
})
.always(function() {
    alert('Ajax запрос завершен');
});




Лучшие практики

Как мы видели выше, код контроллера может быть очень простым, благодаря классу JResponseJson. Модель обрабатывает данные, которые потом могут быть направлены непосредственно в объект JResponseJson. Контроллер лучше всего сохранять в файле mycontroller.json.php и размещать его в папке controllers. Таким образом, этот контроллер будет вызван автоматически, если URL содержит format=json.

Также не забывайте, что нет надобности в закрытии приложения (например, $app->close()), так как Joomla API сделает это за вас.

Удачной разработки!