9

我的控制器中有任务run。我希望它返回 JSON 数据。就目前而言,我将我的 JSON 数据包装在模板 HTML 中。我如何告诉 Joomla 从控制器返回 JSON 数据?这是我的功能:

public function run  ( ) {

    JFactory::getDocument()->setMimeEncoding( 'application/json' );

    JResponse::setHeader('Content-Disposition','attachment;filename="progress-report-results.json"');

    JRequest::setVar('tmpl','component');

    $data = array(
        'foo' => 'bar'
    );

    echo json_encode( $data );

}

这会返回:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-gb" lang="en-gb" dir="ltr">
...
</head>
<body class="contentpane">

<div id="system-message-container">
</div>
    {"foo":"bar"}
</body>
</html>

我想得到:

{"foo":"bar"}
4

7 回答 7

17

您不需要构建一个特殊的 JSON 视图(view.json.php; 或控制器progressreports.json.php)来实现这一点。您唯一需要做的就是回显 JSON 字符串并关闭应用程序。

public function run( )
{
    JFactory::getDocument()->setMimeEncoding( 'application/json' );
    JResponse::setHeader('Content-Disposition','attachment;filename="progress-report-results.json"');

    $data = array(
        'foo' => 'bar'
    );
    echo json_encode( $data );
    JFactory::getApplication()->close(); // or jexit();
}

如果您想提供具有 HTML 和 JSON 输出(由调用者选择)的相同功能,您只需要一个单独的视图(或控制器)。

于 2013-05-25T17:42:30.247 回答
4

现有控制器中的快速方法

您需要用于jexit()返回没有任何 Joomla 输出的 json 数据。

public function run  ( ) {

    $data = array(
        'foo' => 'bar'
    );

    echo json_encode( $data );
    jexit();

}

Joomla 3.x 方法

更好的选择是创建 JSON 控制器并使用 JResponseJson 输出 JSON。文件名应具有 JSON 后缀。例如,如果您的控制器是一个项目,那么您的文件名可以是item.json.php,您可以添加控制器代码,如下所示。

public function run  ( ) {
  $data = array(
    'foo' => 'bar'
  );
  echo new JResponseJson($data);
}

输出将是如下所示的 json。

{"success":true,"message":null,"messages":null,"data":["foo": "bar"]}

你的 ajax URL 应该有 json 参数来触发这个 json 控制器。

index.php?option=com_mycomponent&task=item.run&format=json

使用 JResponseJson 来通知错误和消息。在以下位置阅读完整的文档。

https://docs.joomla.org/JSON_Responses_with_JResponseJson

于 2013-05-24T19:31:50.637 回答
2

得到了答案。

我需要制作一个新的控制器。在我的例子中,原始控制器被称为progressreports.php - 我制作了一个名为progressreports.raw.php 的新控制器。

然后在调用url的时候,加上format=raw。IE

index.php?option=com_foo&task=progressreports.run&format=raw
于 2013-05-24T16:55:22.847 回答
1

根据您所做的事情,您可能想要制作一个 json 文档,无论是whatever.json.php,而不是whatever.html.php。

于 2013-05-25T00:49:59.030 回答
1

我检查了接受的答案,它不适用于 joomla 3.4.3。如果有人有同样的问题,这里是较低 joomla 版本的解决方案:

$data = array(
    'foo' => 'bar'
);
header('content-type: application/json; charset=utf-8');
echo json_encode($data);
JFactory::getApplication()->close();

仅当您要提供文件以供下载时,才需要 content-disposition 标头。

off:我只是想结束这个项目,喝点酒忘记它。即使从头开始编写新的 CMS 也不会那么痛苦。:S

于 2017-03-04T03:40:09.223 回答
1

Joomla 4

您必须将参数&format=json添加到您的 URL。这告诉系统您正在等待 json 响应。系统将呈现 JsonDocument 并将发送正确的浏览器标头作为响应。

index.php?option=com_foo&task=report.run&format=json
class Report extends BaseController {

   public function run() {
       $data = [
         'foo' => 'bar'
       ];

       $response = new ResponseJson($data);

       echo $response;
   }
}

无需使用$app->close(); 关闭应用程序;因为 Joomla 的架构会为您处理这些问题。

如果你关闭应用程序,你会在渲染过程中错过很多东西。许多事件不会被触发。此外,您必须手动发送内容类型的标题。

您的代码应如下所示。不推荐这种方法。

class Report extends BaseController {

   public function run() {

       $this->app->mimeType = 'application/json';
       $this->app->setHeader('Content-Type', $this->app->mimeType . '; charset=' . $this->app->charSet);
       $this->app->sendHeaders();

       $data = [
         'foo' => 'bar'
       ];

       $response = new ResponseJson($data);

       echo $response;

       $this->app->close();
   }
}
于 2020-12-19T19:48:23.810 回答
0

我不太喜欢 JResponseJson,而且我喜欢为下一个请求排队消息,所以我在组件的主控制器上做了以下方法:

public function returnJson($data)
{
    $app = Factory::getApplication();

    // Persist messages if they exist. (Same as CMSApplication->redirect)
    $session = \JFactory::getSession();
    $session->set('application.queue', $app->getMessageQueue());

    // Send json mime type.
    $app->mimeType = 'application/json';
    $app->setHeader('Content-Type', $app->mimeType . '; charset=' . $app->charSet);
    $app->sendHeaders();

    echo json_encode($data);

    $app->close();
}

在控制器或子控制器的任何任务中,您现在可以执行以下操作:

public function sampleTask()
{
    $app = Factory::getApplication();
    $app->enqueueMessage("Done (for the next user's request)", 'success');
    $this->returnJson("json data");
}
于 2018-05-27T15:45:20.877 回答