Symfony jmsserilaizerbundle配置不起作用

时间:2018-08-14 14:25:17

标签: symfony fosrestbundle jmsserializerbundle nelmioapidocbundle

我想使用symfony php框架创建自己的Restful API。 当然,我用 - FOSRestBundle - FOSUserBundle - LexikJWTAuthenticationBundle - JMSSerializerBundle

配置完所有捆绑包后,我的API返回空对象。

[{}{}{}{}{}{}{}]

在我的控制器中我写

class ChantController extends Controller
{
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();
        $chants = $em->getRepository(Chant::class)->findAll();

        return new JsonResponse($chants);
    }
}

由LexikJWTAuthenticationBundle创建的登录api可以正常工作,但是我自己的路由不起作用。 这是我的配置文件

app / config / config.yml

imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: "@ChantBundle/Resources/config/services.yml" }
- { resource: "@UserBundle/Resources/config/services.yml" }
- { resource: "@AdminBundle/Resources/config/services.yml" }
- { resource: "@JsonApiBundle/Resources/config/services.yml" }
- { resource: "@AjaxApiBundle/Resources/config/services.yml" }

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
  locale: fr
  jms_serializer.camel_case_naming_strategy.class: JMS\Serializer\Naming\IdenticalPropertyNamingStrategy

framework:
  #esi: ~
  translator: { fallbacks: ['%locale%'] }
  secret: '%secret%'
  router:
    resource: '%kernel.project_dir%/app/config/routing.yml'
    strict_requirements: ~
  form: ~
  csrf_protection: ~
  validation: { enable_annotations: true }
  #serializer: { enable_annotations: true }
  default_locale: '%locale%'
  trusted_hosts: ~
  session:
    # https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
    handler_id: session.handler.native_file
    save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
  fragments: ~
  http_method_override: true
  assets: ~
  php_errors:
    log: true
  templating:
    engines: ['twig']
  serializer:
    enabled: false

# Twig Configuration
twig:
  debug: '%kernel.debug%'
  strict_variables: '%kernel.debug%'

# Doctrine Configuration
doctrine:
  dbal:
    driver: pdo_mysql
    host: '%database_host%'
    port: '%database_port%'
    dbname: '%database_name%'
    user: '%database_user%'
    password: '%database_password%'
    charset: UTF8
    # if using pdo_sqlite as your database driver:
    #   1. add the path in parameters.yml
    #     e.g. database_path: '%kernel.project_dir%/var/data/data.sqlite'
    #   2. Uncomment database_path in parameters.yml.dist
    #   3. Uncomment next line:
    #path: '%database_path%'

  orm:
    auto_generate_proxy_classes: '%kernel.debug%'
    naming_strategy: doctrine.orm.naming_strategy.underscore
    auto_mapping: true

# Swiftmailer Configuration
swiftmailer:
  transport: '%mailer_transport%'
  host: '%mailer_host%'
  username: '%mailer_user%'
  password: '%mailer_password%'
  spool: { type: memory }

# FOSUserbundle Configuration
fos_user:
  db_driver:     orm                                # Le type de BDD à utiliser, nous utilisons l'ORM Doctrine depuis le début
  firewall_name: main                               # Le nom du firewall derrière lequel on utilisera ces utilisateurs
  user_class:    Root\ModelsBundle\Entity\User\User # La classe de l'entité User que nous utilisons
  #    group:
  #        group_class:  Root\ModelsBundle\Entity\User\Group
  #        form:
  #            type: Root\UserBundle\Form\Type\GroupType
  #    registration:
  #        confirmation:
  #            enabled: true
  #            template: UserBundle:Registration:email.html.twig
  #        form:
  #            type: Root\UserBundle\Form\RegistrationType
  #            validation_groups: [public_registration, Registration]
  #    profile:
  #        form:
  #            type:  Root\UserBundle\Form\Type\ProfileFormType
  #            validation_groups: [public_edit, Default]
  #    resetting:
  #        email:
  #            template: UserBundle:Resetting:email.html.twig
  from_email:
    address:        "%mailer_user%"
    sender_name:    CHORISTER_USER
#    service:
#                mailer: fos_user.mailer.twig_swift

nelmio_api_doc: ~

# JMS Serializer
jms_serializer:
  metadata:
    auto_detection: true
  handlers:
    datetime:
      default_format: "Y-m-d\\TH:i:sP"
      default_timezone: "UTC"

fos_rest:
  body_converter:
    enabled: true
  format_listener:
    rules:
    - { path: '^/api', priorities: ['json'], fallback_format: json, prefer_extension: false }
    - { path: '^/', priorities: ['html'], fallback_format: html, prefer_extension: false }
  view:
    view_response_listener: force
    formats:
      json: true
      xml:  false
  routing_loader:
    default_format: json
  serializer:
    serialize_null: true
  param_fetcher_listener: true
  body_listener: true
  access_denied_listener:
    json: true

# Lexik JWT Auth
lexik_jwt_authentication:
  private_key_path: '%jwt_private_key_path%'
  public_key_path:  '%jwt_public_key_path%'
  pass_phrase:      '%jwt_key_pass_phrase%'
  token_ttl:        '%jwt_token_ttl%'

app / config / security.yml

# To get started with security, check out the documentation:
# https://symfony.com/doc/current/security.html
security:
  encoders:
    FOS\UserBundle\Model\UserInterface: bcrypt

  role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN

  providers:
    fos_userbundle:
      id: fos_user.user_provider.username_email

  firewalls:
    api_docs:
      pattern: ^/doc
      anonymous: true

    login:
      pattern:  ^/api/login
      stateless: true
      anonymous: true
      form_login:
        check_path: /api/login_check
        require_previous_session: false
        username_parameter: username
        password_parameter: password
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure

    api:
      pattern:   ^/api
      stateless: true
      anonymous: true
      lexik_jwt:
        authorization_header:
          enabled: true
          prefix:  Bearer
        query_parameter:
          enabled: true
          name:    bearer

    main:
      pattern: ^/
      logout_on_user_change: true
      form_login:
        provider: fos_userbundle
        csrf_token_generator: security.csrf.token_manager

      logout:       true
      anonymous:    true
      remember_me:
        secret:     "%secret%" # %secret% est un paramètre de parameter
        # pour que l'user restz connecté longtemps
        lifetime: 31536000 # 365 days in seconds
        path: /
        domain: ~ # Defaults to the current domain from $_SERVER
        always_remember_me: true
        remember_me_parameter: _remember_me

  access_control:
  - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
  #        - { path: ^/, role: ROLE_USER }
  - { path: ^/admin/, role: ROLE_ADMIN }
  - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/api,       roles: IS_AUTHENTICATED_ANONYMOUSLY }

请帮忙吗?

已更新

我为此更改了代码:

public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();
        $chants = $em->getRepository(Chant::class)->findAll();

        $data = $this->get('jms_serializer')->serialize($chants, 'json', SerializationContext::create()->setGroups(array('list')));

        $response = new Response($data);
        $response->headers->set('Content-Type', 'application/json');

        return $response;
    }

1 个答案:

答案 0 :(得分:0)

要做的事情:

您的类应扩展FOSRestController以使用REST功能。

class ChantController extends FOSRestController

您可以像这样序列化并返回响应:

 public function listAction(ParamFetcherInterface $paramFetcher, Request $request)
{
    //...your code...//
    $yourObjectifiedResult = $getRepository('yourentity')->findBy(['var' => $var]);
    $yourNormalizedResult = $this->normalizeWithCircularHandler(
                $yourObjectifiedResult,
                ['groups']);
    //Serializer will convert your result from Object to Json Array automatically. To get a specific set of data, you can use groups.
    $response = new JsonResponse(['success' => true, 'data' => $yourNormalizedResult ]);
            $response->setStatusCode(Response::HTTP_OK);
            return $response;
}

public function normalizeWithCircularHandler($data, $displayGroups, $normalizerCallbacks = false)
{
    $encoder = new JsonEncoder();

    $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
    $normalizer = new ObjectNormalizer($classMetadataFactory);

    $normalizer->setCircularReferenceHandler(function ($object) {
        return $object->getId();
    });

    if(false != $normalizerCallbacks && is_array($normalizerCallbacks)) {
        $normalizer->setCallbacks($normalizerCallbacks);
    }

    $serializer = new Serializer([$normalizer], [$encoder]);

    return $serializer->normalize($data , null, ['groups' => $displayGroups]);
}

有关序列化的信息:http://symfony.com/doc/current/components/serializer.html

有关序列化组的信息:https://symfony.com/blog/new-in-symfony-2-7-serialization-groups