Symfony2:从控制器回显JSON以用于ExtJS 4网格


Symfony2: Echoing JSON From a Controller for Use in an ExtJS 4 Grid

我刚开始使用Symfony2,我正试图弄清楚从控制器(例如People)中回显JSON的正确方法是什么,以便在ExtJS 4网格中使用。

当我使用普通MVC方法做所有事情时,我的控制器会有一个类似getList的方法,它会调用People模型的getList方法,得到这些结果,然后做这样的事情:

<?php
class PeopleController extends controller {
    public function getList() {
        $model = new People();
        $data = $model->getList();
        echo json_encode(array(
            'success' => true,
            'root' => 'people',
            'rows' => $data['rows'],
            'count' => $data['count']
        ));
    }
}
?>
  • Symfony2的这种行为是什么样子的
  • 控制器是否适合这种行为
  • (Symfony内部)解决此类问题的最佳实践是什么

控制器是否适合这种行为?

是的。

Symfony2的这种行为是什么样子的?

(Symfony内部)解决此类问题的最佳实践是什么?

在symfony中,它看起来很像,但有一些细微差别。

我想就这件事提出我的方法。让我们从路由开始:

# src/Scope/YourBundle/Resources/config/routing.yml
ScopeYourBundle_people_list:
    pattern:  /people
    defaults: { _controller: ScopeYourBundle:People:list, _format: json }

_format参数不是必需的,但稍后您将了解它的重要性。

现在让我们来看看控制器

<?php
// src/Scope/YourBundle/Controller/PeopleController.php
namespace Overseer'MainBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Controller'Controller; 
class PeopleController extends Controller
{   
  public function listAction()
  {
    $request = $this->getRequest();
    // if ajax only is going to be used uncomment next lines
    //if (!$request->isXmlHttpRequest())
      //throw $this->createNotFoundException('The page is not found');
    $repository = $this->getDoctrine()
          ->getRepository('ScopeYourBundle:People');
    // now you have to retrieve data from people repository.
    // If the following code looks unfamiliar read http://symfony.com/doc/current/book/doctrine.html
    $items = $repository->findAll();
    // or you can use something more sophisticated:
    $items = $repository->findPage($request->query->get('page'), $request->query->get('limit'));
    // the line above would work provided you have created "findPage" function in your repository
    // yes, here we are retrieving "_format" from routing. In our case it's json
    $format = $request->getRequestFormat();
    return $this->render('::base.'.$format.'.twig', array('data' => array(
      'success' => true,
      'rows' => $items,
      // and so on
    )));
  }
  // ...
}    

控制器以路由配置中设置的格式呈现数据。在我们的例子中,它是json格式。

以下是可能的模板示例:

{# app/Resourses/views/base.json.twig #}
{{ data | json_encode | raw }}

这种方法的优点(我的意思是使用_format)是,如果您决定从json切换到例如xml,那么没有问题——只需在路由配置中替换_format,当然,还可以创建相应的模板。

我会避免使用模板来呈现数据,因为转义数据等的责任在模板中。相反,我在PHP中使用了内置的json_encode函数,正如您所建议的那样。

按照前面的回答中的建议,在routing.yml中设置到控制器的路线:

ScopeYourBundle_people_list:
pattern:  /people
defaults: { _controller: ScopeYourBundle:People:list, _format: json }

唯一的附加步骤是强制在响应中进行编码。

<?php
class PeopleController extends controller {
    public function listAction() {
        $model = new People();
        $data = $model->getList();
        $data = array(
            'success' => true,
            'root' => 'people',
            'rows' => $data['rows'],
            'count' => $data['count']
        );
        $response = new 'Symfony'Component'HttpFoundation'Response(json_encode($data));
        $response->headers->set('Content-Type', 'application/json');
        return $response;
    }
}
?>

要使用return new JsonResponse(array('a' => 'value', 'b' => 'another-value');,需要使用正确的命名空间:

use Symfony'Component'HttpFoundation'JsonResponse;

如下所述:http://symfony.com/doc/current/components/http_foundation/introduction.html#creating-a-json响应

您也可以使用内置的JsonResponse,而不是构建自己的响应。

你可以像其他建议的答案一样定义路线:

ScopeYourBundle_people_list:
pattern:  /people
defaults: { _controller: ScopeYourBundle:People:list, _format: json }

并使用新的响应类型:

<?php
class PeopleController extends controller {
    public function listAction() {
        $model = new People();
        $data = $model->getList();
        $data = array(
            'success' => true,
            'root' => 'people',
            'rows' => $data['rows'],
            'count' => $data['count']
        );
        return new 'Symfony'Component'HttpFoundation'JsonResponse($data);
    }
}

有关更多信息,请参阅api或doc(2.6版)。

简单。使用FOSRestBundle并仅从控制器返回People对象。

使用

    return JsonResponse($data, StatusCode, Headers);