Combining view layer and automatic route generation - php

I am having problems including FOSRestBundle in my Symfony 2.1 project.
When I use automatic route generation ( documentation ) and want to use the view layer ( documentation ).
I receive an exception: No route found for "GET /users".
My config.yml:
fos_rest:
routing_loader:
default_format: json
My routing.yml:
users:
type: rest
resource: Api\UserBundle\Controller\UsersController
My UsersController class:
namespace Api\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\RestBundle\Controller\FOSRestController;
class UsersController extends FOSRestController
{
public function getUsersAction() { die('get'); }
public function postUsersAction() { die('post'); }
}
When I remove extends FOSRestController everything works - but I lose the view layer functionality. Anyone who can steer me in the right direction to solving this problem?

I don't know if you manage to solve it by now... But I had the very same problem and it seems to come from the fact that FOSRestController implements ClassResourceInterface (FOSRestBundle will determine the resource based on the Controller name).
All I had to do to make it work was omitting the resource name from the methods.
https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/5-automatic-route-generation_single-restful-controller.md
/ jonas

Related

Symfony Annotation Inheritance

I've got a question about the inheritance of annotations in symfony.
Class A:
abstract class AController
{
/**
* Test action
* #Route("/", name="test")
* #Template("...")
*/
public function testAction()
{
...
}
}
My question is if it is possible from Class B not only to inherit the function but also the route annotation. Or what a nice workaround would be. Something like:
class BController extend AbstractController
{
public function testAction(){
return parent::testAction();
}
}
I was looking for a similar solution for an admin subdomain on a project I'm working on. First, I tried to use your method and realized it isn't supported. So I set updated my configuration instead. The following configuration automatically restricts all routes in the /src/Controller/Admin directory to my admin subdomain and prefixes all the route names with "admin_".
# /config/routes/annotations.yaml
controllers:
resource: ../../src/Controller/**/*
type: annotation
exclude: ../../src/Controller/Admin
admin:
resource: ../../src/Controller/Admin/
type: annotation
host: admin.%site_name%
name_prefix: admin_
....
There's a couple things to note here. First, "%site_name%" is a parameter defined in my project. Second, there seems to be a bug with the exclude option on route configurations where it only works if you use a glob pattern for resource option. Hence the "../../src/Controller/**/*".
This question is pretty old, but hopefully this helps someone.

Symfony where to initialize routes? (routing.yml or inside controller)

On the routing page of smyfony is an routing example (the first one). Now they give us 4 options of code (Annotations, YAML, XML, PHP). Where is the difference? And maybe you can take a look on my Controller + Route.
The controller looks like this:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ToDoListController extends Controller
{
/**
* #Route("/ToDoList", name="ToDoList")
*/
public function showToDoList()
{
}
}
?>
Now I added this route into the routing.yml too.
ToDoList:
path: /Aufgabenliste
defaults: {_controller: AppBundle\Controller \ToDoListController::showToDoList}
Is that correct? Whats about the path? In the first example of the symfony page they wrote defaults: { _controller: AppBundle:Blog:show } but in the description they wrote:
The _controller string is called the logical name. It follows a pattern that points to a specific PHP class and method, in this case the AppBundle\Controller\BlogController::listAction and AppBundle\Controller\BlogController::showAction methods.
Allright. So in Symfony you get to choose between different methods of routing. You can do this for example via annotations or yml(I used to use yml but now I switched to annotations). The only difference is in... format of the file ;) For example I realy like to use annotations because instead of having one billion entries in one file I have every route right next to the code it leads to. At this point for you it depends on what you like better. However I think it's considered as good practice to use annotations.
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ToDoListController extends Controller
{
/**
* #Route("/ToDoList", name="ToDoList")
*/
public function showToDoList()
{
}
}
?>
Code above is ok - you used required namespaces and created correct annotation. All of this you have to do in your bundle you are working on. Also you have to go to app/config/routing.yml and put there something like this:
YourBundleName:
resource: "#YouBundle/Controller/"
type: annotation
Of course it's just an example - you need to adjust it to your needs. This way you are saying to Symfony that you want to use annotations.

Why we use "Action" in Symfony2 controller's methods?

I've just started working my way through the symfony2 book.
I wonder why do we named our controller's functions Action:
public function [something]Action() { // ...
In everyone example in the book thus far and all code I see online Action is the function name. There's any reason for it?
This works perfectly:
<?php
// src/AppBundle/Controller/LuckyController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
class LuckyController extends Controller{
/**
* #Route("/lucky/number/{count}")
*/
public function countTESTING($count){
return new Response(
'<html><body>I DONT HAVE TO CALL THIS somethingACTION</body></html>
');
}
}
?>
I've tried googline this but I see no mention or reasoning as to why. Could someone explain why we use that suffix?
It's just a conventions. You can use those suffixes, but you can also do without it.
If you have
public function somethingAction()
in your controller, you can refer it in the routing configuration in this way:
index:
path: /path_for_something
defaults: { _controller: AppBundle:Index:something }
The _controller parameter uses a simple string pattern called the logical controller name. So, AppBundle:Index:something means:
Bundle: AppBundle
Controller class: IndexController
Method name: somethingAction
But, you can also do this without this feature. Symfony is very flexible, and it does not force you to do almost anything. It is just one of many ways you have to do the same thing.
If you adopt this convention, it's easier for you to understand which action do you have in your controller, it's easy for other developer to understand your code, and it's easier for symfony2 to locate your actions/controllers inside your bundle, so that you can also overriding controllers. This is the best practice.
But if you don't want these benefits, you can using its fully-qualified class name and method as well:
index:
path: /something
defaults: { _controller: AppBundle\Controller\IndexController::indexAction }
But, as the documentation say:
if you follow some simple conventions, the logical name is more
concise and allows more flexibility.
No it wasn't just a naming convention. It was used to execute some code before or after every controller 'action' method. Like checking is user has logged in.
It is based on magic __call function which is executed for a non-existent or non-public method call.
$controller = new Posts();
$controller->index();
class Posts
{
public function __call($name, $args)
{
//run code before
call_user_func_array()[$this, "$nameAction"], $args);
//run code after
}
public function indexAction()
{
}
}
You HAVE TO name your actions
public function somethingAction(){}
because your routes point to a controller, and the action you want to call.
you can also have private functions in your controller, that you will only name
private function something(){}
I say that using yml to configure controllers, i dont believe its different when using annotations, but my advise is to use yml for configuring controllers... really !

FileLoaderException: Cannot import resource "mycontroller" from "C:/wamp/www/Symfony/app/config\routing.yml

I just followed the tutorial about single route on github for this bundle : https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/5-automatic-route-generation_single-restful-controller.md
But I got this error when I'm trying to load my home page:
"FileLoaderException: Cannot import resource "ADC\OgppBundle\Controller\OgppRestController" from "C:/wamp/www/Symfony/app/config\routing.yml" (Class could not be determined for Controller identified by "ADC\OgppBundle\Controller\OgppRestController".)
I know this is some basic stuff but I cannot make it work. Here is the code :
app/config/routing.yml
adc_rest:
resource: ADC\OgppBundle\Controller\OgppRestController
type: rest
ADC\OgppBundle\Controller\OgppRest.php
namespace ADC\OgppBundle\Controller;
use FOS\RestBundle\Controller\Annotations\View;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class OgppRestController extends Controller
{
public function getProfilesAction()
{
} // "get_profiles" [GET] /profile/all
public function getProfileAction($id)
{
} // "get_profile" [GET] /profile/{id}
}
EDIT : I tried to clear the cache in dev environment but when I do it I have the same issue.
Hope this helps
I don't know how FOSRestBundle works (I've never used it), but I think your controller file name is wrong, it should be OgppRestController.php, not OgppRest.php.

Symfony 2 dependency injection

I'm learning symfony 2 dependency injection system. I'm trying to inject Response object in a controller.
ServiceController.php
namespace LD\LearnBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ServiceController extends Controller
{
public function indexAction(Response $response)
{
}
}
Here is the content of services.yml file (please note that it's included in app/config/config.yml
services:
ld_response:
class: Symfony\Component\HttpFoundation\Response
ld_bla:
class: LD\LearnBundle\ServiceController
arguments: ["#ld_response"]
When I try to access ServiceController I get
Class LD\LearnBundle\Controller\Response does not exist
500 Internal Server Error - ReflectionException
What I'm doing wrong?
There are 2 things wrong here:
1: "Class LD\LearnBundle\Controller\Response does not exist"
The class doesn't exist. You used Response without importing the namespace, so the error message is quite explicit here.
2: You shouldn't inject the response. It doesn't make any sense at all. The response is not a service, it's a value that should be passed down through method parameters.
Here's the fix:
namespace LD\LearnBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response; // was missing
class ServiceController extends Controller
{
public function indexAction()
{
return new Response(); // The Controller is responsible of creating the Response.
}
}
Generally, Class <current-namespace>\class does not exist errors hint to a missing use statement.
May I add that:
you shouldn't declare your services in the app/config/config.yml file (create a specific services.yml file. Even better: create it in a bundle)
you shouldn't inject the Response object: it is the responsibility of the controller to create it

Categories