Best way to change routes loading order - symfony

I have routes in my controller loaded in /config/routes/annotations.yaml
controllers:
resource: ../../src/Controller/
type: annotation
I have routes in /config/routes.yaml
about:
path: /about
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
defaults:
template: front/about.html.twig
...
Dynamic routes in "controllers" are overriding my "static" routes.
What is the best way to load "static" routes before those in controllers.
I made it work by commenting the content in /config/routes/annotations.yaml and pasting it in the end of /config/routes.yaml but I don't feel it's the best way to do it...

Technically this might not be enough though. Any route loaded after this will be ignored, and if you are using annotations, you have to put this action in the last action of the last controller sorted alphabetically.
Configure this route in yml, and put it at the end of routes.yml.
This route will be the last to execute (performance hit), and it will catch all requests, so make sure you throw 404-s properly.
(Am I right in assuming that the client wants to be able to configure routes completely? eg CMS pages? Had that situation a couple of times)

It didn't want to change my url nor using the alphabetical trick as suggested in the comments.
I fixed it by changing the order of imported routes in the kernel.
Instead of:
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
}
I
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
# routes loaded in routes.yaml
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
# routes loaded in routes/annotations.yaml
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
}

You can avoid changing the kernel logic by putting the controller with annotations after the static route in routes.xml:
browserconfig:
path: /browserconfig.xml
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
defaults:
template: browserconfig.xml.twig
app_document:
resource: App\Controller\DocumentController
type: annotation

Related

Custom views (or routes) in FOSRestController

I am using FOSRest Bundle to implement Rest API's.
I have the function getTermsAction() which returns all the terms from the DB.
I have a template listTerms.html.twig which shows the list of terms.
I want to implement another function listTermsAction() which will render this template and return it.
Something like this (I added this to my controller)
/**
* #Route("/listTerms",name="listTerms")
*/
public function listTermsAction()
{
$view = $this->view(null,200)
->setTemplate("TermsBundle:Default:listTerms.html.twig");
return $this->handleView($view);
}
I tried to this by adding the following code in routing.yml file
list_terms:
pattern: /terms/listTerms
defaults: {_controller:TermsBundle:Terms:listTermsAction}
But it doesn't work!
It just shows me "null" in the browser
The Solution i have given works but that snippet should be above the rest route in my routing.yml
That is routing.yml should be like
list_term:
pattern: /terms/listTerms
defaults: {_controller:TermsBundle:Terms:listTerms}
terms:
resource: Madhuri\TermsBundle\Controller\TermsController
type: rest
prefix: /
list_term route should be above terms route

Iron Router: Get the name of the current controller

I know you can get the name of the current route's name with Router.current().route.getName(), but how can I get the name of the current route's controller?
Here is an example of how I define my controller(s):
Router.configure
layoutTemplate: 'LayoutFluid'
yieldRegions:
"footer": {to: "footer"}
"header": {to: "header"}
#QuantifyController = RouteController.extend
layoutTemplate: "LayoutSidebar"
yieldRegions:
"footer": {to: "footer"}
"header": {to: "header"}
"QuantifyMenu": {to: "sidebar"}
action: ->
#render()
Router.map ->
#route "Home",
path: "/"
#route "Blog",
path: "/blog"
#route "QuantifyIndex",
path: "/quantify"
controller: "QuantifyController"
#route "QuantifyNewProject",
path: "/quantify/new"
controller: "QuantifyController"
#route "Quantify..." #you get the idea
FWIW, the reason I need to get this is for CSS purposes. I am adding the route's name as a css class to the body, which means that when defining shared styles for views that use the QuantifyController, I need to do body.QuantifyIndex, body.QuantifyNewProject, body.Quantify... which means every time I add a new Quantify.. route I need to also add it to the css which is simply not ideal. If I can get the controller name I can just use body.QuantifyController {...} in the CSS which is much more ideal.
Got it! After hours of searching, I found it defined at:
Router.current().route.options.controller.
Note that if the current controller is the default controller (RouteController) you will get undefined.
#SG_ your comment helped me get there. thanks again.

Troubleshooting "The controller for URI is not callable" error

I'm working on Symfony 2.3 and I declared a new route and new controller, but when I call this controller from the browser I get this error:
The controller for URI "/user/1" is not callable. in /dev.mydomain.org/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php at line 82
This is my simple route configuration:
user_homepage:
pattern: /user
defaults: { _controller: UserBundle:Default:index }
user_show:
pattern: /user/{id}
defaults: { _controller: UserBundle:Default:show }
requirements:
id: \d+
And this is my very simple controller:
public function showUserAction($id)
{
return $this->render('UserBundle:Default:show.html.twig', array());
}
What is wrong?
The logical name UserBundle:Default:show refers to UserBunde\Controller\DefaultController::showAction you have a method called showUserAction.
Either change the method name to showAction or change the logical name to UserBundle:Default:showUser.
Although not relevant to the example given, this error can also be caused if the controller Action is not public
You're defining your controller function as showUserAction while in the definition your saying it is show[Action].
Either change your route configuration
user_show:
pattern: /user/{id}
defaults: { _controller: UserBundle:Default:showUser }
requirements:
id: \d+
or change your controller signature
public function showAction($id)
{
See if this helps
After big search, this worked for me:
1.- Create CRUDController
// src/Acme/DemoBundle/Controller/CRUDController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Inter\PimeBundle\Entity\Empresa;
class CRUDController extends Controller
{
public function publicarAction($id)
{
//code here...
}
}
2.- Create the service
# app/config/config.yml
services:
ebtity.admin.service:
class: Acme\DemoBundle\Admin\EntityAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: group, label: label }
arguments:
- NULL
- Acme\DemoBundle\Entity\Entity
- AcmeDemoBundle:EntityAdmin
3.- Create the template for the action button
{# src/Acme/DemoBundle/Resources/views/CRUD/list__action_publicar.html.twig #}
<a class="btn btn-sm" href="{{ admin.generateObjectUrl('publicar', object) }}">Publicar</a>
4.- Configure route
// src/Acme/DemoBundle/Admin/EntityAdmin.php
namespace Acme\DemoBundle\Admin;
// ...
use Sonata\AdminBundle\Route\RouteCollection;
class EntityAdmin extends Admin
{
// ...
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('engine')
->add('rescueEngine')
->add('createdAt')
->add('_action', 'actions', array(
'actions' => array(
'publicar' => array(
'template' => 'AcmeDemoBundle:CRUD:list__action_publicar.html.twig'
)
)
));
}
protected function configureRoutes(RouteCollection $collection)
{
$collection
->add('publicar',
$this->getRouterIdParameter().'/publicar',
array('_controller' => 'AcmeDemoBundle:CRUD:publicar')
);
}
}
5.- Clear cache
Hope it helps
Not the case here. But there is another related issue:
If you forget the 'Action' suffix all will work. But when you realized that you forget the suffix and then add it ... surprise! Same error as the OP.
The problem here is about caching
Symfony creates two file for caching urls:
AppDevUrlGenerator.php
AppDevUrlMatcher.php
If you change your action name (i.e. adding 'Action' suffix) then that cache info is obsolete.
Solution
php app/console cache:clear
Similar to the accepted answer, if your controller is defined as a service, e.g. (in YAML):
services:
user.default:
class: \UserBundle\DefaultController
And your route uses this controller service:
user_show:
pattern: /user/{id}
defaults: { _controller: user.default:showUserAction }
requirements:
id: \d+
Then it's necessary to name the action method in full including the Action suffix, otherwise you will get the "controller ... is not callable" error.
In my case, i was using symfony 2.
Prior version of symfony maintain method naming convention. Method suffix should contain Action word.
example:
in route yml file the method definition was
docudex_report_make_authorization:
pattern: /make-authorization
defaults: { _controller: DocudexReportBundle:Default:makeAuthorization }
and in the controller the method was
public function makeAuthorization(){}
therefore i was getting the error.
After changing the method name to public function makeAuthorizationAction it worked perfectly.
I would like to share my experience & how I solved it:
I was importing one bundle in an application whose routes were defined using annotations and they were importing fine in application too by using:
auth_bundle_routes:
# loads routes from the given routing file stored in some bundle
resource: '#XyzAuthBundle/Controller/'
type: annotation
But since my bundle controllers were defined using services, Symfony was showing error:
The controller for URI "/facebook/request-code" is not callable.
Controller Xyz\AuthBundle\Controller\FacebookController" has required
constructor arguments and does not exist in the container. Did you
forget to define such a service?
I updated my bundle for routing to use routing.yaml file over annotations and referring to controllers as service::method syntax and then this error is gone.
xyz_auth.facebook_request_code:
path: /facebook/request-code
controller: xyz_auth.controller.facebook_controller::requestCode
Bundle routes must be imported using
auth_bundle_routes:
resource: '#XyzAuthBundle/Resources/config/routing.yaml'
Hope this will save someone's time.
The same issue could happen if your env uses .env.local.php and new changes are added to env files without running composer dump-env
One of the reasons for this error is that you missed to add the word "Action" after the controller's method name. If you think that your routing is OK, check the method name.

Setting index route in Symfony 2

I've got Symfony2 installed, and a mostly working site, the only issue is I don't know how to set a default route. Currently, I access my index and other routes with the following URLs:
www.example.com/app_dev.php/index
www.example.com/app_dev.php/example_route
I'd like to have www.example.com default to the index route, so I can get the same results with the following URLs:
www.example.com
www.example.com/example_route
I'm running lighttpd as my web server. How can I configure lighttpd/Symfony2 to do this?
Just create a route that maps to the / pattern :
# app/config/routing.yml
homepage:
pattern: /
defaults: { _controller: AcmeHomeBundle:home:show }
This will route to whatever controller you specify.
Great Docs:
How to Configure a Redirect without a custom Controller
Routing
I used below code to set home page route.It's working fine
Symfony version : Symfony 3.2.8
homepage:
path: /
defaults: { _controller: AppBundle:Home:index}
For me Symfony 4.1.x
Edit the file
# app/config/routes.yaml
index:
path: /
controller: App\Controller\YourIndexController::yourIndexFunction
There's
App\Controller is the namespace you declare at the start of the Controller class, and after is your class name and method name to route to.
I solved this problem by just removing the following from routing_dev.yml
_welcome:
pattern: /
defaults: { _controller: AcmeDemoBundle:Welcome:index }
That is assuming you have setup a default / route in a routing.yml file or by defining the route in a controller like:
/**
* #Route("/")
* #Template()
*/
public function indexAction()
{
return array('name' => '1');
}
The answer given by ManseUK is very much helpful but I have little elaboration
1)
# app/config/routing.yml
homepage:
pattern: /
defaults: { _controller: AcmeHomeBundle:home:show }
2) rename the app_dev.php to index.php and this will route to the home page automatically

Get routing requirement variable in Symfony2

in order to create a navigation for me webinterface I'd like to get a variable from the routing config of my bundle. I define the available pages in mybundle/Resources/config/routing.yml.
mybundle_homepage:
pattern: /{_locale}/{branch}/{page}
defaults: { _controller: mybundle:mycontroller:index, _locale: de, branch: x.x.x, page: start }
requirements:
_locale: de|en
page: start|functions|events|constants|styleguide
Now I had a look at the Symfony2 YAML Parser and I have to provide a filepath to it's static method parse: http://symfony.com/doc/2.0/reference/YAML.html
mycontroller.php
use Symfony\Component\Yaml\Yaml;
class mycontroller extends Controller
{
public function indexAction($_locale, $branch, $page)
{
$routing = Yaml::parse('../Resources/config/routing.yml');
var_dump($routing);
}
}
I thought I could do it that way because the folder hirarchy looks like that:
mybundle
Controller
mycontroller.php
Rescources
config
routing.yml
But it's not working. Any ideas or maybe another way to get the requirements.page array from the routing file?
Regards, Ben
You should be able to access the router service inside a class that's DI container aware. So, you can write something like:
$routes = $this->container->get('router')->getRouteCollection();
$route = $routes->get('my_route_name');
print_r($route->getRequirements());

Resources