如何使用 FOSRestBundle return 或以 JSON 格式显示数据

How to return or display data in JSON format using FOSRestBundle

我正在使用 Symfony2 和 FOSRestBundle 在 Restful API 中工作。我已阅读 view layer 文档,但我不清楚如何处理 API 的输出。我想实现的很简单:显示或 return 或将结果输出为有效 JSON。这是我在控制器上的内容:

<?php

/**
 * RestAPI:       Company.
 */
namespace PDI\PDOneBundle\Controller\Rest;

use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\Annotations\Get;

class CompanyRestController extends FOSRestController
{
    /**
     * Gets all companies.
     *
     * @return array
     *
     * @ApiDoc(
     *   resource = true,
     *       https = true,
     *   description = "Gets all companies",
     *   statusCodes = {
     *      200 = "Returned when successful",
     *      400 = "Returned when errors"
     *   }
     * )
     * @Get("/api/v1/companies")
     *
     */
    public function getCompaniesAction()
    {
        $response = array();
        $em = $this->getDoctrine()->getManager();
        $entities = $em->getRepository('PDOneBundle:Company')->findAll();

        if ($entities) {
            foreach ($entities as $entity) {
                $response['companies'][] = [
                    'id' => $entity->getId(),
                    'createdAt' => $entity->getCreatedAt(),
                    'updatedAt' => $entity->getUpdatedAt(),
                    'name' => $entity->getName(),
                    'logo_url' => $entity->getLogoUrl(),
                    'division' => $entity->getDivision(),
                    'inactive' => $entity->getInactive(),
                ];
            }

            $response['status'] = 'ok';
        } else {
            $response['status'] = 'error';
        }

        return $response;
    }
}

如果我尝试这个 URL: /app_dev.php/api/v1/companies.json 我收到 404 错误:

{"code":404,"message":"No route found for \"GET\/api\/v1\/companies.json\""}

如果我尝试这个 URL:https://reptool.dev/app_dev.php/api/v1/companies 错误打开:

Unable to find template "". 500 Internal Server Error - InvalidArgumentException 3 linked Exceptions: Twig_Error_Loader » InvalidArgumentException » InvalidArgumentException »

我也检查了 FOSRestBundleByExample 但没有得到太多帮助。

我在这里缺少什么?我如何实现我所需要的?有什么建议吗?

FOSRest 配置

我忘记在 config.yml 添加 FOSRestBundle:

#FOSRestBundle
fos_rest:
    param_fetcher_listener: true
    body_listener: true
    format_listener:
        rules:
            - { path: ^/, priorities: [ json, html ], fallback_format: ~, prefer_extension: true }
        media_type:
            version_regex: '/(v|version)=(?P<version>[0-9\.]+)/'

    body_converter:
        enabled: true
        validate: true

    view:
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
        view_response_listener: 'force'
        formats:
            xml:  false
            json: true
        templating_formats:
            html: true

    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
    allowed_methods_listener: true
    access_denied_listener:
        json: true

我感受到你的痛苦。我在开始时也遇到了麻烦。一个重要的起点是配置。这是我在实施中使用的内容。

fos_rest:
    param_fetcher_listener: true
    view:
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
        view_response_listener: 'force'
        formats:
            xml:  false
            json: true
        templating_formats:
            html: true
    format_listener:
        rules:
            - { path: ^/, priorities: [ json, html ], fallback_format: ~, prefer_extension: true }
        media_type:
            version_regex: '/(v|version)=(?P<version>[0-9\.]+)/'
    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
    allowed_methods_listener: true
    access_denied_listener:
        json: true
    body_listener: true

format_listener 中,如果您希望 JSON 成为默认响应,请确保将其设置为优先级第一。否则你的 header 每次都需要包含 Accept: application/json。这可能就是您在尝试使用 twig 呈现 HTML 输出时遇到 twig 错误的原因。

此外,请确保您安装了 http://jmsyst.com/bundles/JMSSerializerBundle 之类的序列化程序并将其包含在您的 AppKernal 中。

在您的控制器中,我发现像您一样扩展 FOSRestController 最简单,而且 return 视图 object 而不是自己创建数组。序列化程序将为您处理所有这些。

/**
 * RestAPI:       Company.
 */
namespace PDI\PDOneBundle\Controller\Rest;

use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\Annotations\Get;

class CompanyRestController extends FOSRestController
{
    /**
     * Gets all companies.
     *
     * @return array
     *
     * @ApiDoc(
     *   resource = true,
     *       https = true,
     *   description = "Gets all companies",
     *   statusCodes = {
     *      200 = "Returned when successful",
     *      400 = "Returned when errors"
     *   }
     * )
     * @Get("/api/v1/companies")
     *
     */
    public function getCompaniesAction()
    {
        $response = array();
        $em = $this->getDoctrine()->getManager();
        $entities = $em->getRepository('PDOneBundle:Company')->findAll();
        if(!$entities)
        {
             return $this->view(null, 400);
        }

        return $this->view($entities, 200);
    }
}

希望对您有所帮助。