1

I'm quiet new to symfony and spend hours trying to find a solution. I'm building a multilingual website where page slugs are differents. For example :

www.mywebsite.com/products EN will be www.mywebsite.com/produits FR but both use the same controller

I have to build a dynamic route and here is the way I did I'm pretty sure I can do better, could you help me?

<?php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class websiteController{

    public function __construct(){

        $this -> route = array(
            'about' => 'page_about',
            'contact' => 'page_contact',
        );

    }

     /**
     * @Route("/{page}", name="page")
     */
    public function pageAction($page)
    {

        if($page == $this -> route['about']){
            return new Response('<html><body>page about</body></html>');
        }

        if($page == $this -> route['contact']){
            return new Response('<html><body>page contact</body></html>');
        }

    }
}
?>

1 Answer 1

2

There is a bundle for routing internationalization called BeSimpleI18nRoutingBundle but it is not available for symfony 4 right now.


Core symfony implementation

With core symfony you could use multiple routes for each controller, that would have a {_locale} parameter with default value, here the problem would be that two different URLs would be returning the same page.

e.g /test would be the same as /test/en

This might cause problems with SEO

here how the annotations would look like if you wish to implement this method

/**
 * @Route("/test/{_locale}", defaults={"_locale"="en"}, requirements={"_locale":"en"}, name="default_en")
 * @Route("/δοκιμή/{_locale}", defaults={"_locale"="el"}, requirements={"_locale":"el"}, name="default_el", options = {"utf8": true})
 * @Route("/tester/{_locale}", defaults={"_locale"="fr"}, requirements={"_locale":"fr"}, name="default_fr")
 */
public function test($_locale)
{
    return new Response("Your current locale is : $_locale");
}

Dynamic Route

Another option is to create a Routing Service that would apply your logic. Here is an example.

this would be the controller that handles all the paths

Controller

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use App\Service\Router;

class RouterController extends Controller {

    /**
    * @Route("/{path}", name="router", requirements={"path" = ".+"})
    */
    public function router($path,Request $request,Router $router) {

        $result=$router->handle($path);

        if($result){
            $result['args']['request']=$request;
            return $this->forward($result['class'], $result['args']);
        }


        throw $this->createNotFoundException('error page not found!');        
    }

}

This Controller Action depends on a service called Router so you will have to create a Router service that would return the an array (you can change it to return a custom object) with keys class and args that would be used to forward the request to a controller action.

Service

/src/Service/Router.php

Here you should implement a function called handle and you can apply any logic to it

here is a basic example

namespace App\Service;

class Router
{

    public function handle($path)
    {
        switch ($path) {
            case "test":
                return [
                    "class" => "App\Controller\TestController::index",
                    "args"  => [
                        "locale" => 'en'
                    ]
                ];
            case "tester":
                return [
                    "class" => "App\Controller\TestController::index",
                    "args"  => [
                        "locale" => 'fr'
                    ]
                ];
            default:
                return false;
        }
    }
}

The code above would forward the request to TestController::index function and will add as parameter to that function the locale variable and also it will include the Request object

You could store the routes in a yaml file or database or any other location you like. You can manipulate the $path variable to extract information about id, page etc.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. I'm able to make it work at time. I was thinking about a more human and conventional way to do that. Simply generate the .yaml file according to the slug the admin will define. Do you think it might be a good idea? In a way i'll be able to go on using some of the Yaml component features.
@raphaman I do not know if you still interested in that issue, but there were some news, in symfony 4.1 they will support route internationalization out of the box. You can take a look here symfony.com/blog/new-in-symfony-4-1-internationalized-routing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.