-->

Unable to find template when returning response wi

2019-04-11 23:35发布

问题:

I'm using FOS Rest Bundle to build an Api, the problem is that every time I try to return anything I get the error message: "Unable to find template" I don't really want to render a template, but to serialize an entity that I have.

Here is my code:

routing.yml:

acme_api_register:
    pattern: /user
    defaults: { _controller: AcmeApiBundle:User:post, _format: json }
    requirements:
          _method: POST

controller.php:

<?php

namespace Acme\ApiBundle\Controller;

use Acme\ApiBundle\Entity\Patient;
use Acme\ApiBundle\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use FOS\RestBundle\Controller\Annotations\View;

//use FOS\RestBundle\View\View;

    class UserController extends Controller
    {
        /**
         * @View()
         */
        public function postAction()
        {
            $user = new Patient();

            $user->setName("Daniel");
            $user->setLastName("My lastName");
            $user->setEmail("pleasework@gmail.com");

            return $user;
        }
    }

and my app/config.yml

sensio_framework_extra:
    view: { annotations: false}
    router: { annotations: true }

fos_rest:
    format_listener:
        rules:
            - prefer_extension: false
    routing_loader:
        default_format: json
    view:
        view_response_listener: force

I would appreciate any help a lot!

PD:

composer.json:

{
    "name": "symfony/framework-standard-edition",
    "license": "MIT",
    "type": "project",
    "description": "The \"Symfony Standard Edition\" distribution",
    "autoload": {
        "psr-0": { "": "src/" }
    },
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "~2.4",
        "doctrine/orm": "~2.2,>=2.2.3",
        "doctrine/doctrine-bundle": "~1.2",
        "twig/extensions": "~1.0",
        "symfony/assetic-bundle": "~2.3",
        "symfony/swiftmailer-bundle": "~2.3",
        "symfony/monolog-bundle": "~2.4",
        "sensio/distribution-bundle": "~2.3",
        "sensio/framework-extra-bundle": "~3.0",
        "sensio/generator-bundle": "~2.3",
        "incenteev/composer-parameter-handler": "~2.0",
        "friendsofsymfony/rest-bundle": "1.1.*",
        "jms/serializer-bundle": "0.13.*"
    },
    "scripts": {
        "post-install-cmd": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
        ],
        "post-update-cmd": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
        ]
    },
    "config": {
        "bin-dir": "bin"
    },
    "extra": {
        "symfony-app-dir": "app",
        "symfony-web-dir": "web",
        "symfony-assets-install": "symlink",
        "incenteev-parameters": {
            "file": "app/config/parameters.yml"
        },
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}

回答1:

This happens because you're probably using a browser to test your API. If you open your console inspector you'll see what's the request your browser is sending to your API. As you can see the Accept header looks something like:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

As you can see the first accepted format is text/html. That's why I guess your application is trying to return an HTML response, but it can't find the template!

So I suggest you disable the html format if you don't need it and set json as the default format.

fos_rest:
    param_fetcher_listener: true
    format_listener:
        rules:
            fallback_format: json
            prefer_extension: false
            priorities: [json, xml]
    view:
        view_response_listener: force
        formats:
            json: true
            xml: true
            jsonp: false
            rss: false
            html: false
        failed_validation: HTTP_BAD_REQUEST

With such configuration you're saying that the only formats you support are json and xml and, if none is specified, use json. Now open your browser again and you'll get your resource as an XML. That's because the Accept header is still Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8. Your browser doesn't know you're calling a Rest API and what's your preferred format :-)

To test your API I suggest you use a proper client. If you're using Chrome then take a look at the Advanced REST client extension.



回答2:

I think you are using the wrong controller, try using the FOSRestController instead. Your controller code should be something like this.

<?php

    namespace Acme\ApiBundle\Controller;

    use Acme\ApiBundle\Entity\Patient;
    use Acme\ApiBundle\Entity\User;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use FOS\RestBundle\Controller\Annotations\View;
    use FOS\RestBundle\Controller\FOSRestController;


    class UserController extends FOSRestController
    {
        /**
         * @View()
         */
        public function postUserAction()
        {
            $user = new Patient();

            $user->setName("Daniel");
            $user->setLastName("My lastName");
            $user->setEmail("pleasework@gmail.com");

            return $user;
        }
    }

For more info take a look over here

Also your routing should be defined like this.

routing.yml

users:
    type:     rest
    resource: Acme\ApiBundle\Controller\UsersController

FOSRest can automatically generate the routes for you if you stick to the rules as explained in the documentation.

Please take your time and read the documentation since it looks obvious that you didn't if I look at your code.



回答3:

I know you said in a comment you were giving up but you should try this if you still want to build a REST api. I think your config.yml is wrong. You have to specify what is the priority of the page formats to be sure that the first selected is json (even if you wrote it in the route, it's not enough).

Try to change your config file to be like this :

#...
fos_rest:
    view:
        view_response_listener: force
    format_listener:
        default_priorities: ['json', 'html', '*/*']
        fallback_format: json
        prefer_extension: true
#...

Here is a really good article on how to build correct REST Api :

http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/