Symfony translating routes using BeSimple/BeSimpleI18nRoutingBundle duplicate routes - php

I'm creating a multi language website and I'm using BeSimple/BeSimpleI18nRoutingBundle for route translations. Route in my config looks like that:
about:
locales: { en: "/{_locale}/about-us", lt: "/{_locale}/apie-mus" }
defaults: { _controller: BaseBundle:Base:about }
However in this case I get duplicate route as if I enter /en/about-us or /lt/about-us it works in both ways. but in the second way it should be 404 error because the route for lt locale should be /lt/apie-mus which also works fine.
Is there any way of fixing that? Or maybe any better ways of translating routes?

However in this case I get duplicate route
There is one route per language:
$ app/console router:debug
about.en ANY ANY ANY /{_locale}/about-us
about.lt ANY ANY ANY /{_locale}/apie-mus
When you are on the URL /lt/about-us the UrlMatcher will match the en version:
$ app/console router:match /lt/about-us
Route "about.en" matches
[router] Route "about.en"
Name about.en
Path /{_locale}/about-us
Path Regex #^/(?P<_locale>[^/]++)/about\-us$#s
Host ANY
Host Regex
Scheme ANY
Method ANY
Class Symfony\Component\Routing\Route
Defaults _controller: AppBundle:Default:index
_locale: en
Requirements NO CUSTOM
Options compiler_class: Symfony\Component\Routing\RouteCompiler
In this case, the local will be en and not lt.
But I don't think that you should worry about it because the only way that a visitor will visite /lt/about-us is by editing the URL himself.

After battle with BeSimple I switched my project to JMSI18nRoutingBundle in 10 minutes. It works well and resolves problem with routes. Firstly: it containes multiple modes of prefixation (with locale) and secondly it allows to translate every route.

Related

Is it possible to construct a Symfony path using only parameters?

I would like to reduce the number of repetitive code and give a canonical URL in my Drupal 8 application. Since the routing system is built on Symfony, I included it in the title.
I am constructing paths under routes in my mymodule.routing.yml file. I want to match a specified number of different strings in the first argument, and a slug which can be any string in the second argument. It looks like this:
entity.my_entity.canonical:
path: '/{type}/{slug}'
defaults:
_controller: '\namespace\PostController::show'
requirements:
_permission: 'perm'
type: different|strings|that|can|match|
Now, when I try to access using for example /match/some-slug then it just says "Page not found".
If I something static to the path, for example path: '/j/{type}/{slug}', then it works as expected when I open /j/match/some-slug in the browser.
My boss doesn't like any unnecessary characters in the URL though, so I would like to achieve this by using two parameters, like shown in the first example.
As Yonel mentioned in the comments you can use debug:router to check all your routes. I don't see anything wrong with your code.
Try running bin/console router:match "/match/blaaa" and if you see some controller that isn't the one you want then you'll need to change the route. It shouldn't be the case though because you're getting a 404.
Here's my exact setup that works
routing.yml:
entity.my_entity.canonical:
path: '/{type}/{slug}'
defaults:
_controller: 'MyBundle:Something:foo'
requirements:
type: different|strings|that|can|match|
Inside MyBundle\SomethingController:
public function fooAction($id)
{
return new Response("bar");
}
Then going to http://localhost/match/fom shows the "bar" response.
I have read the documentation again (RTM), and found out that it is not possible in Drupal 8, while it is possible in Symfony.
Note that the first item of the path must not be dynamic.
Source: Structure of routes in Drupal 8

Symfony2 routes redirecting to wrong controller

In my symfony2 application I want specific routes for my pages, to work well with my seo, but I receive some serious problems and I dont understand them..
EXAMPLE:
Two routes:
blog_article:
path: /blog/{slug}
defaults: {_controller: ApplicationEDBlogBundle:Blog:singleArticle}
product:
path: /{category}/{name}
defaults: { _controller: MpShopBundle:Product:view}
The product route works fine, but the blog_article route always redirects to product route..
In my understanding if i open blog: /blog/firstBlog/ by default it thinks that the blog is a category and firstBlog is the product name, because my product route is the last route.
But if in my twig i specificaly tell which route to go to, shouldnt it work?
For example: {{ path('blog_article', {slug: blog.slug}) }}. Shouldnt this look at the blog_article route and open the needed controller? Or it does not work like that?
If so, how to keep my pretty urls the way I want to?
change routing to
blog_article:
path: /blog/{slug}
defaults: {_controller: ApplicationEDBlogBundle:Blog:singleArticle}
product:
path: /cat/{category}/{name}
defaults: { _controller: MpShopBundle:Product:view}
and will be fine .
In your example {category} could be "blog" , so 1st route was matched .
It can also work if you change order ( product w'll be first). But it's not good solution (what if someone add category blog ?)
Nope, it doesn't work like that, i.e. your example path code doesn't mean that the routing should look for the blog_article route:
The twig path function just expands the route into the actual url (/blog/yourslug) and when actually accessing that url, the system makes the matching the other way around from the url to the route (matching to whichever happens to be the first of the above listed two route definitions).
If you have this kind of routes, the solution is to have them neatly in the correct order (most generic ones - the product in this case - being always the last), or if the ordering is not possible, you can try to solve this by placing some specific route requirements if applicable.

Different host and routes in Symfony witho JMS i18n

I want different host and different routes in my multicountry web with Symfony 3. I used the JMS i18n routing for this.
My config YML file:
jms_i18n_routing:
default_locale: es_ES
locales: [es_ES, fr_FR, en_GB]
strategy: custom
hosts:
es_ES: www.aaa.local
fr_FR: www.aaa-fr.local
en_GB: www.aaa-uk.local
redirect_to_host: true
With this, I can use different host correctly, but I don't know how I can "translate" the routes, f.ex: /contacto /contact and /contact.
I want load differents routing.yml depends on the locale.
When using the JMSI18nRoutingBundle your routes are being Translated automatically based on your route_name using the routes domain (Symfony Translation Component).
So, assumed your route_name is contact, just create a Translations like this:
id/source: contact
domain: routes
locale: en
translation/target: /contact
id/source: contact
domain: routes
locale: es
translation/target: /contacto
Now your routes using the Symfony router (which is wrapped by the one from the bundle) will return automatically the translated route from the current locale.
If you want to translate it to a specific locale, just add the route parameter _locale like this:
{{ path("contact", {"_locale": "es"}) }}
or
$this->get('router')->generate('contact', array('_locale' => 'es'));

Silex add route with higher priority than existing routes

My Silex routes are defined in a routing.yml config file.
In my php code I would like to add some new routes dynamically and I want these routes to have a higher priority than the routes defined in routing.yml.
Currently I'm adding my routes as in the following example, but they are added to the bottom, i.e. with the lowest priority.
$this->app->match('/page/{slug}', array($this, 'record'))
->bind('extrapages')
->method('GET|POST');
This route for example never gets matched because there is a route in routing.yml that matches the following path:
path: /{contenttypeslug}/{slug}
How do add my new routes above the existing routes?
As an aside I'm using the Bolt CMS, which is built on Silex, and trying to add these new routes in a bolt extension. As this question is about Silex routing the fact that I'm using Bolt shouldn't make a great deal of difference.
It's not a very clean solution but whenever I've overruled an extension's route in my routing.yml, I just add the extension's route to routing.yml again, pointing it to my extension code. If you put it near the top, it will get used, because in Silex routes are parsed 'top down'. First match gets used.
sitemap:
path: /sitemap
defaults:
_controller: 'Bolt\Extension\Bolt\Sitemap\Extension::sitemap'
I apologize for the hackyness of this solution.

Routing in Symfony2

How to setup default routing in Symfony2?
In Symfony1 it looked something like this:
homepage:
url: /
param: { module: default, action: index }
default_symfony:
url: /symfony/:action/...
param: { module: default }
default_index:
url: /:module
param: { action: index }
default:
url: /:module/:action/...
I was looking through the cookbook for an answer to this, and think I've found it here. By default, all route parameters have a hidden requirement that they match any character except the / character ([^/]+), but this behaviour can be overridden with the requirements keyword, by forcing it to match any character.
The following should create a default route that catches all others - and as such, should come last in your routing config, as any following routes will never match. To ensure it matches "/" as well, a default value for the url parameter is included.
default_route:
pattern: /{url}
defaults: { _controller: AcmeBundle:Default:index, url: "index" }
requirements:
url: ".+"
I don't think it's possible with the standard routing component.
Take a look to this bundle, it might help :
https://github.com/hidenorigoto/DefaultRouteBundle
// Symfony2 PR10
in routing.yml:
default:
pattern: /{_controller}
It enables you to use this kind of urls: http://localhost/MySuperBundle:MyController:myview
Symfony2 standard routing component does not support it, but this bundle fills the gap Symfony1 left:
https://github.com/LeaseWeb/LswDefaultRoutingBundle
It does what you expect. You can default route a bundle using this syntax:
FosUserBundle:
resource: "#FosUserBundle"
prefix: /
type: default
It scans your bundle and automatically adds routes to your router table that you can debug by executing:
app/console router:debug
Example of automatically added default routes:
[router] Current routes
Name Method Pattern
fos_user.user.login_check ANY /user/login_check.{_format}
fos_user.user.logout ANY /user/logout.{_format}
fos_user.user.login ANY /user/login.{_format}
...
You see that it also supports the automatic "format" selection by using a file extension (html, json or xml).
Here is an example: http://docs.symfony-reloaded.org/master/quick_tour/the_big_picture.html#routing
A route definition has only one mandatory parameter pattern and three optionals parameters defaults, requirements and options.
Here's a route from my own project:
video:
pattern: /watch/{id}/{slug}
defaults: { _controller: SiteBundle:Video:watch }
requirements: { id: "\d+", slug: "[\w-]+"
Alternatively, you can use #Route annotation directly in a controller file. see https://github.com/sensio/SensioFrameworkExtraBundle/blob/master/Resources/doc/annotations/routing.rst
As for the default routes, I think Symfony2 encourages explicit route mapping.
Create a default route is not a good way of programming. Why? Because for this reason was implemented Exception.
Symfony2 is built just to do right things in the right way.
If you want to redirect all "not found" routes you should use exception, like NotFound404 or something similar. You can even customise this page at your own.
One route is for one purpose. Always. Other think is bad.
You could create your own bundle that handled all requests and used URL parameters to construct a string to pass to the controller's forward method. But that's pretty crappy, I'd go with well defined routes, it keeps your URLs cleaner, and decouples the URL and controller names. If you rename a bundle or something, do you then have to refactor your URLs?
If you want to create a "catch all", your best bet would be to hook on the KernelEvents::EXCEPTION event. This event gets triggered whenever an Exception falls through to the HttpKernel, this includes the NotFoundHttpException thrown when the router cannot resolve a route to a Controller.
The effect would be similar to Symfony's stylized 404 page that gets rendered when you send the request through app_dev.php. Instead of returning a 404, you perform whatever logic you're looking to.
It depends... Some of mine look like this:
api_email:
resource: "#MApiBundle/Resources/config/routing_email.yml"
prefix: /
and some look like
api_images:
path: /images/{listingId}/{width}/{fileName}
defaults: { _controller: ApiBundle:Image:view, listingId: null, width: null, fileName: null }
methods: [GET]
requirements:
fileName: .+

Categories