Как вернуть или отобразить данные в формате JSON с помощью FOSRestBundle

Я работаю в Restful API, используя Symfony2 и FOSRestBundle. Я прочитал документы представления, но не ясно мне, как обрабатывать вывод для API. Чего я хочу добиться, так это просто: отображать или возвращать или выводить результат как действительный 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:

Не удалось найти шаблон "". 500 Внутренняя ошибка сервера — InvalidArgumentException 3 связанные исключения: Twig_Error_Loader » InvalidArgumentException » InvalidArgumentException »

Я также проверил FOSRestBundleByExample, но не получил большой помощи.

Что мне здесь не хватает? Как мне достичь того, что мне нужно? Любой совет?

Конфигурация FOSRest

Я забыл добавить FOSRestBundle в config.yml:

#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

person ReynierPM    schedule 06.05.2015    source источник


Ответы (1)


Я чувствую твою боль. У меня тоже были проблемы с запуском. Одним из важных мест для начала является конфигурация. Вот что я использую в своей реализации.

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 был ответом по умолчанию, убедитесь, что он установлен первым в приоритетах. В противном случае ваш заголовок должен будет каждый раз включать Accept: application/json. Возможно, поэтому вы получаете ошибку twig, поскольку она пытается использовать twig для вывода вывода HTML.

Кроме того, убедитесь, что у вас установлен и включен сериализатор, такой как http://jmsyst.com/bundles/JMSSerializerBundle. в вашем AppKernal.

В вашем контроллере мне было проще расширить FOSRestController, как это сделали вы, но также вернуть объект представления вместо того, чтобы создавать массив самостоятельно. Сериализатор сделает все это за вас.

/**
 * 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);
    }
}

Надеюсь, это немного поможет.

person Squeegy    schedule 06.05.2015
comment
Я сделал то, что вы сказали мне, но все еще получаю ту же проблему, связанную с просмотром, что может быть не так? Я также добавил конфигурацию в основной пост, вы можете взглянуть? - person ReynierPM; 06.05.2015