9
votes

I need a variable on a prefix on my symfony2 routing so that i can do something like this in the main routing file:

//app/config/routing.yml
god:
    resource: "@Acme/DemoBundle/Resources/config/routing.yml"
    prefix: /god/{religion}

and then something like this in the bundle routing file:

gods_route_to_heaven:
    path: /path_to_heaven
    defaults: { _controller: AcmeBlogBundle:God:show }

so that i can access paths like this:

/god/Christianity/path_to_heaven
/god/Islam/path_to_heaven
/god/Hinduism/path_to_heaven

and so on.

If i type app/console route:debug | grep api on the console i get the correct route /god/{religion}/path_to_heaven, so the route is being generated correctly.

But when I try to get the parameter in the controller by placing it as an input in the action function like this:

public function showAction($religion)

the path gets corrupted and dumping the paths i see it gets duplicated: /god/{religion}/path_to_heaven/{religion}

So how would i get the $religion variable from inside the controller?

5

5 Answers

3
votes

Have you tried this?

//app/config/routing.yml
god:
    resource: "@Acme/DemoBundle/Resources/config/routing.yml"
    prefix: /god

and then something like this in the bundle routing file:

gods_route_to_heaven:
    path: /{religion}/path_to_heaven
    defaults: { _controller: AcmeBlogBundle:God:show }

Let me know if it works.

2
votes

the possible solution you need, would be:

File: src/Acme/CoreBundle/Twig/PathExtension.php

<?php

namespace Acme\CoreBundle\Twig\Extension;

use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;

class PathExtension extends \Twig_Extension
{

    private $request;
    private $router;

    public function __construct(Router $router) {
        $this->router = $router;
    }

    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->getRequestType() === HttpKernel::MASTER_REQUEST) {
            $this->request = $event->getRequest();
        }
    }

    public function getFunctions()
    {
        return array(
            'path_route' => new \Twig_Function_Method($this, 'getPath')
        );
    }

    public function getPath($name, $parameters = array())
    {
        $parameters = array_merge($parameters, [
            'religion' => $this->request->get('religion'),
        ]);

        return $this->router->generate($name, $parameters, false);
    }

    public function getName()
    {
        return 'twig_path_route_extension';
    }

}

Configuration as service:

File: src/Acme/CoreBundle/Resources/config/services.yml

services:
    twig.path_route_extension:
        class: Acme\CoreBundle\Twig\PathExtension
        tags:
            - { name: twig.extension }
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
        arguments: [@router]

Set your routing options:

File: app/config/routing.yml

_acme_religion:
    resource: "@AcmeCoreBundle/Resources/config/routing.yml"
    prefix:   /god/{religion}/

Then you can use it in the templates and the routing.yml, for ex:

_religion_pathheaven:
    path:     /path_to_heaven
    defaults: { _controller: AcmeCoreBundle:System:getpathheaven }

Then, in your templates, you can use:

<a href="{{ path_route('_religion_pathheaven') }}">
  Link Path to heaven.
</a>

References:

Pass path parameters automatically http://blog.viison.com/post/15619033835/symfony2-twig-extension-switch-locale-current-route

0
votes

You may solve this problem in this way-

god:
    resource: "@Acme/DemoBundle/Resources/config/routing.yml"
    prefix: /god/{_locale}/

no need to change in here--

gods_route_to_heaven:
    path: /path_to_heaven
    defaults: { _controller: AcmeBlogBundle:God:show }

modification in here--

    public function showAction(){
       // below line is extra if you need
         $post   = $this->get('request')->request->all();
         $religion = $post['religion']; 
    }

I didn't test this code but all process is well proved. If you will see any problem let discuss.

Also you may see this question it will help you very much Symfony2 Route global {_locale} requirements

0
votes

May be it's to late, but it can help other people
I'm facing the same problème with Symfony and FOSUserBundle.
In FOSUserBundle the profile link are :

site_url/profile/
site_url/profile/edit
site_url/profile/change-password

I have an admin and dashboard panel, and I want the links to be in admin panel

site_url/admin/profile/
site_url/admin/profile/edit
site_url/admin/profile/change-password

and in the user dashboard

site_url/dashboard/profile/
site_url/dashboard/profile/edit
site_url/dashboard/profile/change-password

To get this behavior it's very simple without EventListener and TwigExtesion
Here the solution:

replace

fos_user:
    resource: "@FOSUserBundle/Resources/config/routing/all.xml"

by

fos_user_security:
    resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_registration:
    resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
fos_user_resetting:
    resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
fos_user_change_password:
    resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
    prefix:   /{prefix}/profile 
fos_user_profile:
    resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
    prefix:   /{prefix}/profile

In a template use:

<a href="{{ path('fos_user_profile_show', {'prefix': 'dashboard'}) }}">Show Profile</a>
<a href="{{ path('fos_user_profile_edit', {'prefix': 'dashboard'}) }}">Edit Profile</a>
<a href="{{ path('fos_user_change_password', {'prefix': 'dashboard'}) }}">Change Password</a>

Or any other prefix you want
Now if you use for example the change password link you will get this error

An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("prefix") to generate a URL for route "fos_user_change_password".") in FOSUserBundle:ChangePassword:changePassword_content.html.twig at line 3.

you can add the prefix in the template like so:
replace

<form action="{{ path('fos_user_change_password') }}" {{ form_enctype(form) }} method="POST" class="fos_user_change_password"> 

by

<form action="{{ path('fos_user_change_password', {'prefix': app.request.attributes.get('prefix') }) }}" {{ form_enctype(form) }} method="POST" class="fos_user_change_password">

this will give you this error

Some mandatory parameters are missing ("prefix") to generate a URL for route "fos_user_profile_show".

the final solution that I found is to override the controller
just copy the hole controle in your app controller folder,change the namesapce and replace

if (null === $response = $event->getResponse()) {
                $url = $this->generateUrl('fos_user_profile_show');
                $response = new RedirectResponse($url);
            }

by

if (null === $response = $event->getResponse()) {
                $url = $this->generateUrl('fos_user_profile_show',array('prefix'=>$request->get('prefix')));
                $response = new RedirectResponse($url);
            }

in the form you don't need the action so it will be

<form  {{ form_enctype(form) }} method="POST" class="fos_user_change_password">
0
votes

You can get the religion value like this:

use Symfony\Component\HttpFoundation\Request;

...

public function showAction(Request $request){
   $yourReligionIs = $request->get('religion');
}