Check routing in symfony2 - php

I want to learn symfony and I start to create a small application. I have a question related to the routes. So, I have in my project the routes :
/admin/homepage, /admin/news, admin/galery
No if I write in url /admin, this route doesn't exist and I get as error No route found for "GET /admin/". Exist a way to check if route doesn't exist and redirect to another route for example ? Thx in advance and sorry for my english
My routes :
news_all:
path: /news/all/{page}
defaults: { _controller: AppAdminBundle:News:all, page: 1 }
requirements:
page: \d+
_method: GET|POST
news_add:
path: /news/add
defaults: { _controller: AppAdminBundle:News:add }

In your case the best solution would be to override default ExceptionController and add custom logic there, e.g. redirection to other page - according to the docs: http://symfony.com/doc/current/cookbook/controller/error_pages.html#overriding-the-default-exceptioncontroller
# app/config/config.yml
twig:
exception_controller: AppBundle:Exception:showException
Note:
Instead of creating a new exception controller from scratch you can, of course, also extend the default ExceptionController. In that case, you might want to override one or both of the showAction() and findTemplate() methods. The latter one locates the template to be used.

Symfony's good practise are to set rout in your controller, using annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
and
/**
* #Route("/news/add", name="news_add")
*/
public function addAction()
{
// ...
}
Also, with annotation, you can set rout for a whole controller.
Which is, in your case, what you're looking for.
/**
* #Route("/admin")
*/
class NewsController extends Controller
{
/**
* #Route("/news/add", name="news_add")
*/
public function addAction()
{
// ...
}
}
Also, I advice you to take a look at #Template annotation.
Else, to answer your question, I think you can make a custom twig function (check this link for more information). Function that checks is the given name a valid route:
function routeExists($name)
{
// I assume that you have a link to the container in your twig extension class
$router = $this->container->get('router');
return (null === $router->getRouteCollection()->get($name)) ? false : true;
}

Related

File routing on symfony

I was reviewing the symfony 3.4 routing page. I have a misunderstanding if anyone can help me. So say you have the following:
In Your controller:
class BlogController extends Controller
{
/**
* Matches /blog exactly
*
* #Route("/blog", name="blog_list")
*/
public function listAction()
{
// ...
}
}
And in your routing.yml:
blog_list:
path: /blog
defaults: { _controller: AppBundle:Blog:list }
Would you be able to delete the route annotation above the function. Because now the routing is being handled by the routing.yml?
Many thanks
You must choose one of this methods to set route for current url "/blog"
In Symfony Routing can be declare using YAML, XML, PHP or annotation. It is recommended you stick with only one but you can use multiple approaches in a single project.
Official doc for routing Symfony Routing
and the answer to your question is, I would say yes you could delete the annotation.
Because now the routing is being handled by the routing.yml
for the big project, I prefer YML routing.

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.

How to route to two different 'Action' functions in same controller using annotation - Symfony2

Recently I shifted from Symfony 2.4 to Symfony 2.7
So I was following the new docs. Now say I have 2 action functions in same controller.
public function indexAction() {}
public function changeRateAction()
Previously I would have route them using routing.yml
change_interest_rate_label:
path: /change_interest_rate
defaults: { _controller: appBundle:appInterestRateChange:index }
change_interest_rate_action_label:
path: /change_interest_rate_and_archived_action
defaults: { _controller: appBundle:appInterestRateChange:changeRate }
Now in 2.7 docs, annotations are encourages. Inside controller file
/**
* #Route("/home", name="homepage")
*/
This will fire the action method contains in the controller file. But how can I write annotations for 2 methods for different urls included in the same controller file ?
That means I have indexAction & changeRateAction in same controller file. I want to route url /home with index function and /change with changeRate function. How to do this using annotations ? I know how to do this using routing.yml
You use the annotation routing on a method, not a controller, really.
You just specify the route before every method. In your case it would be something like this:
/**
* #Route("/home", name="homepage")
*/
public function indexAction() {
...
}
/**
* #Route("/change", name="changerate")
*/
public function changeRateAction() {
...
}
Be sure to read more about routing in the documentation: http://symfony.com/doc/current/book/routing.html

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 !

Defining a route in Symfony 2 with variable action

Just imagine, I have a controller with several actions in it.
And to reach each action I have to define it strictly in routing.yml file like this:
admin_edit_routes:
pattern: /administrator/edituser
defaults: { _controller: MyAdminBundle:Default:edituser }
admin_add_routes:
pattern: /administrator/adduser
defaults: { _controller: MyAdminBundle:Default:adduser }
And I can have plenty of such pages. What I want to achieve is to define necessary action in my URI, just like Kohana routes do.
I mean, I want simply to use one route for all actions:
(code below is not valid, just for example)
admin_main_route:
pattern: /administrator/{action}
defaults: { _controller: MyAdminBundle:Default:{action} action:index}
It will pass all requests to /administrator/{anything} to this route, and after that, according to the action, stated in the uri, the needed action is gonna to be called.
If action is not stated in the uri, then we got thrown to index action.
Is it possible in Symfony 2 in any ways and if yes, then how?
Thanking in advance.
This doesn't feel right to do so. By exposing your controller API (methods) "on the fly" directly via GET method, you open your application to security vulnerabilities. This can also easily lead to unwanted behaviours.
Moreover, how would you generate routes in twig for example ? By giving explicit constants tied to the method names?
{{ path('dynamic_route', { 'method': 'addUser' }) }}
This is not how Symfony works nor what it recommands. Symfony is not CodeIgniter nor Kohana. You don't need a second "Front Controller"
If this is a laziness matter, you can switch your routing configurations to annotations. And let Symfony auto-generate the routes you need, with minimal efforts.
namespace Acme\FooBundle\Controller;
/**
* #Route("/administrator")
*/
class DefaultController extends Controller
{
/**
* #Route
*/
public function indexAction(Request $request);
/**
* #Route("/adduser")
*/
public function addUserAction(Request $request);
/**
* #Route("/edituser")
*/
public function editUserAction(Request $request);
/**
* #Route("/{tried}")
*/
public function fallbackAction($tried, Request $request)
{
return $this->indexAction($request);
}
}
The fallbackAction methods, returns any /administrator/* route which does not exist to the indexAction content.
To sum up, I advise not to use dynamic routing "on the fly" directly to method names.
An alternative would be to create a command which will generate routes once executed.
Well, maybe that's not the best way to do that, but it works. Your dynamicAction accepts action string parameter and checks if such action exists. If so, it executes given action with params.
/**
* Default Controller.
*
* #Route("/default")
*/
class DefaultController extends Controller
{
/**
* #Route("/{action}/{params}", name="default_dynamic")
*/
public function dynamicAction($action, $params = null)
{
$action = $action . 'Action';
if (method_exists($this, $action)) {
return $this->{$action}($params);
}
return $this->indexAction();
}
}
I'm curious if someone have any other ideas :>

Categories