方式一:
View服务中注册ViewJsonStrategy之后,就可以直接在控制器的action中是使用JsonViewModel来输出json数据了。
注册ViewJsonStrategy:
//module/Application/module.php
class Module{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('render', array($this, 'registerJsonStrategy'), 100);
}
public function registerJsonStrategy(MvcEvent $e)
{
$app = $e->getTarget();
$locator = $app->getServiceManager();
$view = $locator->get('Zend\View\View');
$jsonStrategy = $locator->get('ViewJsonStrategy');
$view->getEventManager()->attach($jsonStrategy, 100);
}
}
控制器的action中是使用JsonViewModel来输出json数据:
//module/Test/src/Controller/TestController.php
use Zend\View\Model\JsonModel;
class TestController extends AbstractActionController
{
public function unitsAction() {
$resultSet = $this->getUnitTable()->select();
$units = array();
foreach ($resultSet as $unit) {
$units[$unit->idReal] = $unit->name;
}
return new JsonModel($units);
}
}
通过这种方式输出的json数据的Content-type类型是application/json,如果要修改Content-type类型为text/plain,则需要注册一个晚于zf2的Rnder事件监听器的监听器来修改://module/Application/module.php
class Module{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('render', array($this, 'registerJsonStrategy'), 100);
attach(MvcEvent::EVENT_RENDER, function($event){
$event->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
}, -10000);
}
public function registerJsonStrategy(MvcEvent $e)
{
$app = $e->getTarget();
$locator = $app->getServiceManager();
$view = $locator->get('Zend\View\View');
$jsonStrategy = $locator->get('ViewJsonStrategy');
$view->getEventManager()->attach($jsonStrategy, 100);
}
}
方式二:
要实现zf2的控制器输出json数据,主要要解决2个问题,第一个就是修改header头的Content-type部分为
'Content-Type: application/json'或者为'Content-Type: text/json',第二个就是输出json数据。
修改header头,可以手动修改也可以自动修改。
自动修改header头的方式是,使用zf2的JsonRenderer,或者json的view helper:
1)使用JsonRenderer的方法:zf2默认使用PhpRender,因此需要在项目启动的时候,修改renderer。在启动模块(Application)的onBootStrap方法中,添加一个render事件的linstener(registerJsonStratery),
public function onBootstrap($e)
{
// Register a render event
$app = $e->getParam('application');
$app->getEventManager()->attach('render', array($this, 'registerJsonStrategy'), 100);
}
在lisntener中将jsonStratery sttach到View的EventManger上,
public function registerJsonStrategy($e)
{
$matches = $e->getRouteMatch();
$moduleRootName = $matches->getMatchedRouteName();//$moduleaRootName是在module.config.php中配置的route名称
if ($moduleRootName != 'test') { //该模块所有控制器都设置为JsonRenderer
return;
}
$app = $e->getTarget();
$locator = $app->getServiceManager();
$view = $locator->get('Zend\View\View');
$jsonStrategy = $locator->get('ViewJsonStrategy');
$view->getEventManager()->attach($jsonStrategy, 100);
}
2)使用view helper的方法:在控制器里面禁用layout($view->setTerminal(true);)或者在layout里面不要输出任何html,然后view里面json输出,
$arr = array();
$arr[] = 1111;
$arr[] = 'aaaa';
echo $this->json($arr);
手动修改header头的方式,在view里面(禁用layout)或者在layout里面输出,
header('Content-Type: application/json');
zf2提供了json编解码类Zend\Json\Json用于json数据编解码,该类会先尝试使用php函数json_encode和json_decode进行编解码,如果php不支持这2个函数,该类则会使用php脚本进行编解码,因此,在zf2中尽量使用该类而不要使用php的json_encode和json_decode进行编解码。
例子1:让单个控制器的action输出json,
方法一:
//控制器代码
use Zend\Json\Json;
//.......
$arr = array();
$arr[] = 1111;
$arr[] = 'aaaa';
$jsonData = Json::encode($arr);
$view = new ViewModel(array(
'jsonData' => $jsonData
));
$view->setTerminal(true);
return $view;
//或者
$arr = array();
$arr[] = 1111;
$arr[] = 'aaaa';
$view = new ViewModel(array(
'arr' => $arr
));
return $view;
//视图代码
header('Content-Type: application/json');
echo $this->jsonData;
//或者
echo $this->json($this->arr);
方法二:新建一个layout文件如下,
//view/layout/json.phtml
header('Content-Type: application/json');
控制器代码,
use Zend\Json\Json;
//.......
$layout = $this->layout();
$layout->setTemplate('layout/json');
$arr = array();
$arr[] = 1111;
$arr[] = 'aaaa';
$jsonData = Json::encode($arr);
$view = new ViewModel(array(
'jsonData' => $jsonData
));
return $view;
视图代码,
echo $this->jsonData;
例子2:让某个模块或者某个控制器都输出json,将renderer改为JsonRenderer并且更换默认的php layout后,就直接在view中输出json数据了,
public function onRoute(MvcEvent $e)
{
$matches = $e->getRouteMatch();
$moduleRootName = $matches->getMatchedRouteName();//$moduleaRootName是在module.config.php中配置的route名称
if ($moduleRootName != 'test') { //该模块所有控制器都设置为JsonRenderer
return;
}
$controllerName = $matches->getParam('controller');//$controllerName是在module.config.php中配置的controller名称
if ($controllerName != 'Test\Controller\Test') { //该控制器所有actions都设置为JsonRenderer
return;
}
$e->getViewModel()->setTemplate("layout/json");
}
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), -9000);
$eventManager->attach('render', array($this, 'registerJsonStrategy'), 100);
}
public function registerJsonStrategy($e)
{
$matches = $e->getRouteMatch();
$moduleName = $matches->getMatchedRouteName();
$matches = $e->getRouteMatch();
$moduleRootName = $matches->getMatchedRouteName();//$moduleaRootName是在module.config.php中配置的route名称
if ($moduleRootName != 'test') { //该模块所有控制器都设置为JsonRenderer
return;
}
$controllerName = $matches->getParam('controller');//$controllerName是在module.config.php中配置的controller名称
if ($controllerName != 'Test\Controller\Test') { //该控制器所有actions都设置为JsonRenderer
return;
}
$app = $e->getTarget();
$locator = $app->getServiceManager();
$view = $locator->get('Zend\View\View');
$jsonStrategy = $locator->get('ViewJsonStrategy');
$view->getEventManager()->attach($jsonStrategy, 100);
}
之后,就可以直接在浏览器端的javascript中通过ajax获取json数据了:
<script lang="javascript">
$(document).ready(function(){
$("#b01").click(function(){
htmlobj=$.ajax({url:"/test/json",async:false});
alert(htmlobj.responseText);
});
});
</script>
例子3:直接在控制器中返回JsonModel
use Zend\View\Model\JsonModel;
class TestController extends AbstractActionController {
public function uploadprogressAction()
{
$id = $this->params()->fromQuery('id', null);
$progress = new SessionProgress();
return new JsonModel($progress->getProgress($id));
}
}