Symfony2: повторение JSON от контроллера для использования в сетке ExtJS 4
Я только начинаю работать с Symfony2, и я пытаюсь выяснить, какой правильный подход для эхо-ответа JSON от контроллера (например, People
) для использования в сетке ExtJS 4.
Когда я делал все, используя ванильный MVC-подход, мой контроллер имел бы метод, называемый getList
, который вызывает метод People
model 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) для решения этой проблемы?
Ответы
Ответ 1
Является ли контроллер правильным местом для такого поведения?
Да.
Как выглядит это поведение в 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 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 в конфигурации маршрутизации и, конечно же, создайте соответствующий шаблон.
Ответ 2
Я бы не стал использовать шаблон для визуализации данных, так как ответственность за экранирование данных и т.д. затем находится в шаблоне. Вместо этого я использую встроенную функцию json_encode в PHP так же, как вы предложили.
Установите маршрут к контроллеру в 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;
}
}
?>
Ответ 3
Чтобы использовать 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-response
Ответ 4
Вместо создания собственного ответа вы также можете использовать встроенный 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).
Ответ 5
Simple. Используйте FOSRestBundle и возвращайте объект People только из контроллера.
Ответ 6
использовать
return JsonResponse($data, StatusCode, Headers);