【问题标题】:Joomla - Controller task that returns JSON dataJoomla - 返回 JSON 数据的控制器任务
【发布时间】:2013-05-20 08:09:48
【问题描述】:

我的控制器中有任务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"}

【问题讨论】:

    标签: php json joomla joomla2.5


    【解决方案1】:

    得到答案。

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

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

    index.php?option=com_foo&task=progressreports.run&format=raw
    

    【讨论】:

    • 有几种方法可以做到这一点。您所做的是一种方式,Nagarjun 指出了您应该确保为 JSON 请求执行的操作。您还可以使用 progressreports.json.php 控制器并将您的请求更改为 format=json。归根结底,只要它对您有用,那么您就可以开始了。
    【解决方案2】:

    现有控制器中的快速方法

    您需要使用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

    【讨论】:

      【解决方案3】:

      根据您所做的工作,您可能想要制作一个 json 文档,使用whatever.json.php 而不是whatever.html.php。

      【讨论】:

        【解决方案4】:

        您无需构建特殊的 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();
        }
        

        如果你想为 same 函数提供 HTML 和 JSON 输出(由调用者选择),你只需要一个单独的视图(或控制器)。

        【讨论】:

        • 这个答案来自 2013 年,对我不起作用。相反,我使用了 inf3rno 的解决方案,效果很好
        【解决方案5】:

        我检查了接受的答案,它不适用于 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 标头。

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

        【讨论】:

          【解决方案6】:

          我不太喜欢 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");
          }
          

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-05-18
              • 2011-01-20
              • 2013-09-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多