Php 如何在JSON响应中呈现ZF2视图?

Php 如何在JSON响应中呈现ZF2视图?,php,json,zend-framework2,zend-framework-mvc,Php,Json,Zend Framework2,Zend Framework Mvc,到目前为止,我已经了解了如何在Zend Framework 2中返回典型的JSON响应。首先,我将ViewJsonStrategy添加到view\u manager配置的strategies部分。然后,我没有从控制器操作返回ViewModel实例,而是返回一个设置了所有变量的JsonModel实例 现在我已经了解了这一点,我需要了解如何呈现视图并在JSON响应中返回它。在ZF1中,我能够使用$this->view->render($scriptName),它以字符串形式返回HTML。在ZF2中,

到目前为止,我已经了解了如何在Zend Framework 2中返回典型的JSON响应。首先,我将
ViewJsonStrategy
添加到
view\u manager
配置的
strategies
部分。然后,我没有从控制器操作返回
ViewModel
实例,而是返回一个设置了所有变量的
JsonModel
实例

现在我已经了解了这一点,我需要了解如何呈现视图并在JSON响应中返回它。在ZF1中,我能够使用
$this->view->render($scriptName)
,它以字符串形式返回HTML。在ZF2中,
Zend\View\View::render(…)
方法返回
void

所以。。。如何呈现HTML视图脚本并在一个请求中以JSON响应返回它

这就是我现在拥有的:

    if ($this->getRequest()->isXmlHttpRequest()) {
        $jsonModel = new JsonModel(...);

        /* @todo Render HTML script into `$html` variable, and add to `JsonModel` */
        return $jsonModel;
    } else {
        return new ViewModel(...);
    }

和往常一样,框架开发人员在AJAX上搞得一团糟,遵循“为什么简单如果可能很复杂”的规则,这是一个简单的解决方案 在控制器脚本中

public function checkloginAction()
{
   // some hosts need to this some not 
   //header ("Content-type: application/json");  // this work
   // prepare json aray ....
   $arr = $array("some" => .....);
   echo json_encode($arr); // this works
   exit;
}
这也适用于ZF1和ZF2 根本不需要查看scrpt

如果您使用ZF2 creator的建议

use Zend\View\Model\JsonModel;
....


 $result = new JsonModel($arr);
 return $result;

AJAX的响应为空,至少在zf 2.0.0中是这样的好吧,我想我终于明白你在做什么了。我找到了一个我认为符合你标准的解决方案。虽然我确信还有改进的余地,因为还有一些讨厌的手工活要做

public function indexAction()
{
  if (!$this->getRequest()->isXmlHttpRequest()) {
    return array();
  }

  $htmlViewPart = new ViewModel();
  $htmlViewPart->setTerminal(true)
               ->setTemplate('module/controller/action')
               ->setVariables(array(
                  'key' => 'value'
               ));

  $htmlOutput = $this->getServiceLocator()
                     ->get('viewrenderer')
                     ->render($htmlViewPart);

  $jsonModel = new JsonModel();
  $jsonModel->setVariables(array(
    'html' => $htmlOutput,
    'jsonVar1' => 'jsonVal2',
    'jsonArray' => array(1,2,3,4,5,6)
  ));

  return $jsonModel;
}
如您所见,我创建的templateMap是。。。肮脏的这很烦人,我相信可以改进很多。这是一个有效的解决方案,但不是一个干净的解决方案。也许有人能从ServiceLocator中用模板和路径映射获取可能已经实例化的默认PhpRenderer,然后它应该更干净

多亏了@DrBeza的评论,需要完成的工作可以减少相当数量。现在,正如我最初所希望的,我们将在所有模板映射保持不变的情况下获取viewrenderer,并直接渲染ViewModel。唯一重要的因素是您需要指定要呈现的完全限定模板(例如:“$module/$controller/$action”)

不过,我希望这会让您开始;)

PS:响应如下所示:

Object:
    html: "<h1>Hello World</h1>"
    jsonArray: Array[6]
    jsonVar1: "jsonVal2"
对象:
html:“你好,世界”
jsonArray:数组[6]
jsonVar1:“jsonVal2”

您可以使用更简单的方式为JSON响应呈现视图

public function indexAction() {
    $partial = $this->getServiceLocator()->get('viewhelpermanager')->get('partial');
    $data = array(
            'html' => $partial('MyModule/MyPartView.phtml', array("key" => "value")),
            'jsonVar1' => 'jsonVal2',
            'jsonArray' => array(1, 2, 3, 4, 5, 6));
    $isAjax = $this->getRequest()->isXmlHttpRequest());
    return isAjax?new JsonModel($data):new ViewModel($data);
}
请注意,在使用JsonModel类之前,您需要在模块的module.config.php文件中配置视图管理器

'view_manager' => array(
        .................
        'strategies' => array(
            'ViewJsonStrategy',
        ),
        .................
    ),

这是我的工作,希望它能帮助您。

在ZF 3中,您可以使用此代码实现相同的结果

MyControllerFactory.php

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    $renderer = $container->get('ViewRenderer');

    return new MyController(
        $renderer
    );
}
MyController.php

private $renderer;

public function __construct($renderer) {
    $this->renderer = $renderer;
}

public function indexAction() {

    $htmlViewPart = new ViewModel();
    $htmlViewPart
            ->setTerminal(true)
            ->setTemplate('module/controller/action')
            ->setVariables(array('key' => 'value'));

    $htmlOutput = $this->renderer->render($htmlViewPart);

    $json = \Zend\Json\Json::encode(
        array(
            'html' => $htmlOutput,
            'jsonVar1' => 'jsonVal2',
            'jsonArray' => array(1, 2, 3, 4, 5, 6)
        )
    );

    $response = $this->getResponse();
    $response->setContent($json);

    $response->getHeaders()->addHeaders(array(
        'Content-Type' => 'application/json',
    ));
    return $this->response;
}

嘿,既然我也在做这件事,我就回到这件事上来。你到底有什么问题?当返回jsonModel(数组($data))时,响应是json。当返回json时,您不希望呈现任何视图或任何内容OoI需要在json响应中呈现部分视图。示例:
{“html”:“我是一个html响应”}
。我需要在Ajax响应中呈现一个视图脚本。如下:
{“html”:“我是一个html响应”}
。我很欣赏这个响应,但我感觉自己像一个坏记录。这是有帮助的,但它不能回答我的问题。我需要在JSON响应中返回HTML,这将包括其他变量——可能有多个视图。@webjawns.com我已经编辑了我的答案,希望这能让您开始。@Sam您可以使用以下快捷方式实现所有这些:$htmlOutput=$this->getServiceLocator()->get('viewrenderer')->render('test/test',$viewModel)。@DrBeza感谢您的澄清,我认为这是可能的,但simple不知道如何:)我将尝试修改答案:)如果您使用的是Twig,则将
get('viewrenderer')
替换为
get('ZfcTwigRenderer')