Search code examples
jsonrestfosrestbundlesymfony4

FOSRestBundle woes with Symfony4, 204 no content response


I've made a rest controller for Movie objects with a get action.

My database manager one movies with id:3.

enter image description here

When I try to access localhost:8000/api/movie/3 or any other idea for that matter it goes straight back to the page I came from, with only a hint of no content response.

[Tue May 29 16:06:42 2018] 127.0.0.1:61540 [204]: /api/movie/3

I have the following configurations:

services.yaml

services:
    ...
    sensio_framework_extra.view.listener:
        alias: Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener
    ...

routes/rest.yaml

movies:
    type:     rest
    resource: App\Controller\MovieController
    prefix: /api

packages/fos_rest.yaml

fos_rest:
    param_fetcher_listener:  true
    allowed_methods_listener:  true
    routing_loader:
        include_format: false
    view:
        view_response_listener:  'force'
    format_listener:
        rules:
            - { path: '^/api', priorities: ['json'], fallback_format: 'json' }
    zone:
        - { path: ^/api/* }

packages/framework.yaml:

framework:
    ...
    templating: { engines: ['twig'] }

And the following files:

Controller/MovieController.php

<?php

namespace App\Controller;

use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\FOSRestController;

/**
* @Rest\RouteResource("Movie", pluralize=false)
*/
class MovieController extends FOSRestController implements ClassResourceInterface {

    /**
     * @Rest\View()
     * @Rest\Get("/movie/{id}")
     */
    public function getAction(string $id) {}

}

Entity/Movie.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\MovieRepository")
 */
class Movie {
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=32)
     */
    private $title;

    public function __construct($title) {
        $this->title = $title;
    }

    ...
}

Debug router is giving me this result:

$ bin/console debug:router | grep movie
  get_movie                     GET        ANY      ANY    /api/movie/{id}

[update]

Due to earlier wrong configurations I encountered the errors:

1

Warning: ReflectionObject::__construct() expects parameter 1 to be object, null given

2

An instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface >must be injected in FOS\RestBundle\View\ViewHandler to render templates.

3

Type error: Argument 2 passed to Twig_Environment::render() must be of the type array

4

There are no registered paths for namespace "FOSRest".

5

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data


Solution

  • I had to edit MovieController to return the object or return an exception.

    MovieController.php

    <?php
    
    namespace App\Controller;
    
    use App\Repository\MovieRepository;
    use Doctrine\ORM\EntityManagerInterface;
    use FOS\RestBundle\Controller\Annotations as Rest;
    use FOS\RestBundle\Routing\ClassResourceInterface;
    use FOS\RestBundle\Controller\FOSRestController;
    
    
    /**
    * @Rest\RouteResource("Movie", pluralize=false)
    */
    class MovieController extends FOSRestController implements ClassResourceInterface {
    
        /**
         * @var EntityManagerInterface
         */
        private $entityManager;
    
        /**
         * @var MovieRepository
         */
        private $movieRepository;
    
        public function __construct(
            EntityManagerInterface $entityManager,
            MovieRepository $movieRepository
        ) {
            $this->entityManager       = $entityManager;
            $this->movieRepository     = $movieRepository;
        }
    
        public function getAction(string $id) {
            $movie = $this->movieRepository->find($id);
    
            if($movie === null) {
                throw new NotFoundHttpException();
            }
    
            return $this->view($movie);
        }
    }