@RouteResource does not work
Asked Answered
B

3

11

I'm using FosRestBundle and I'm declaring a controller with manually routes.

namespace Cboujon\PropertyBundle\Controller;

use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\View\View;
use FOS\RestBundle\Controller\Annotations\Get;


/**
 * Property controller.
 * @RouteResource("Property")
 */
class PropertyRESTController extends \FOS\RestBundle\Controller\FOSRestController {


    /**
     * 
     * @return type
     * @Get("/types")
     * 
     */
    public function getTypesAction() {
        ...
        return $this->get('fos_rest.view_handler')->handle($view);
    }

}

routing.yml

cboujon_property_property_api:
    resource: "@CboujonPropertyBundle/Controller/PropertyRESTController.php"
    type:     rest
    prefix:   /api

When I do the request http://localhost:8000/api/properties/types or http://localhost:8000/api/property/types I get

404 Not Found - NotFoundHttpException.

But if http://localhost:8000/api/types it works!

I need to config the url http://localhost:8000/api/properties/types. What am I doing wrong?

Update 1

There is no Property entity. PropertyController should do custom operations (No CRUD).

Update 2

You can see the git repository

Belfry answered 5/10, 2015 at 0:44 Comment(3)
The RouteResource looks like it's just to change the name (eg, FooController using the resource Property rather than Foo). It looks like your routing.yml should have parent: property in the definition for the types routes.Perdu
@Qoop, sorry but I don't understand, why my routing.yml should have parent: property? My other controllers defined does not need it and I didn't have any error with them.Belfry
you dont need RouteResource annotation when you will define custom routes for all Controller actions and if you will define prefix for all actions, can use @Prefix anotation on class controllerThug
L
10

You simply cannot mix implicit and explicit route generation (for a single route) in FOSRestBundle.

@RouteResource is meant for "prefixing" during implicit route generation, while @Get is meant for explicit routing.

Also, implicit routing is meant to speedup standard CRUD resource editing, so it is NOT your case: just go for the explicit routing and avoid all the complication. You can still benefit of other FOSRestBundle features, like View handler, @ParamFetchers, ...

Why

With implicit route generation, the route is extracted from the method name (e.g. postTypeAction becomes something like POST /type, cgetTypeAction becomes something like GET /types).

If you choose the explicit way, you use @Route, @Get, @Post, ... annotations, to set the resource URL to whatever you want. With explicit routing, @RouteResource doesn't make sense; just use the standard Symfony prefixes.

The annotation @RouteResource on the other hand, is there so that you can customize the route resource name (e.g. get_RESOURCE_myaction).

Debug you code

To clarify, here some output of app/console debug:router from your code (I've applied some syntax fix to your project to run this commands).

NOTE: I've set the prefix to /api/prefix to avoid confusions

@RouteResource + @Get (This explain why you get 404 errors):

 Name                     Method Scheme Host Path                              
 get_property_types       GET    ANY    ANY  /api/prefix/types.{_format}   

@RouteResource only (note that implicit naming take place):

 Name                     Method Scheme Host Path                              
 get_property_types       GET    ANY    ANY  /api/prefix/property/types.{_format}

@Get only (note it is the same of your current scenario, just the route name changes since is not set in @Get):

 Name                     Method Scheme Host Path                              
 get_types                GET    ANY    ANY  /api/prefix/types.{_format}

Removing both (is still the same, but.. just a coincidence since your method is called getTypesAction):

 Name                     Method Scheme Host Path                              
 get_types                GET    ANY    ANY  /api/prefix/types.{_format}       

An Off-Topic Note

In OOP, a static abstract function cannot be defined. A static method is defined at class level, so no polymorphism can take place because PHP cannot know in advance which sub-class is to be used. When the method is NOT static, PHP knows the object class (since can access $this) and you can have polymorphic behaviour.

In your class Cboujon\PropertyBundle\Entity\Property you need to remove the method static abstract function getLabel or define it as abstract function getLabel.

Limit answered 14/10, 2015 at 13:10 Comment(0)
S
0

If I understood you correctly you should change prefix in routing.yml from

perifx: /api

to

prefix: /api/properties

to have this url http://localhost:8000/api/properties/types

Slightly answered 5/10, 2015 at 9:10 Comment(2)
Michal, I should be able to set the properties part in controller as annotation, not as prefix.Belfry
Another solution could be @Get("/properties/types") but it's ugly.Belfry
S
0

Well, you can simply remove the @GET annotation from your getTypesAction() method and rely on the default route creation behaviour of FOSRestBundle (your method will then be accessible via /api/property/types).

Edit: Basically, this is what is described on http://symfony.com/doc/master/bundles/FOSRestBundle/5-automatic-route-generation_single-restful-controller.html#define-resource-actions.

Surpassing answered 12/10, 2015 at 20:28 Comment(3)
I have been tried remove @GET but I still get 404 error.Belfry
Please, see my Update 2Belfry
Can you please post the output of php app/console debug:router after removing the @GET annotation?Surpassing

© 2022 - 2024 — McMap. All rights reserved.