Silex add route with higher priority than existing routes - php

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.

Related

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.

How to pass a variable to routing defaults in Symfony?

I have a Symfony2 project with multiple brandings (subdomains). Each subdomain should use the same site functions and the same routes (with different hostname). Therefor I want to make the subdomain in the route path to a variable. Now it looks like:
mybundle_route:
resource: "#MyProjectBundle/Controller/"
type: annotation
prefix: /
host: "{subdomain}.%base_host%"
requirements:
subdomain: sub1|sub2
and the routing itself works. But if I try to generate some routes (e.g. in twig), I get following error because no subdomain variable is set:
Some mandatory parameters are missing ("subdomain") to generate a URL for route "company_route".
I don't want to add the parameter to each path() function in the project.
It works perfekt for one subdomain if I add the defaults like this:
defaults:
subdomain: sub1
but the routes are wrong for the other subdomains. Also it doesn't work with
defaults:
subdomain: "%subdomain%"
All I need is to pass the %subdomain% variable to the defaults or to set it somewhere in the controller constructor. But I can't find the way how it is going. I would appreciate any help.
If there is no better solution you could try to set %subdomain% parameter inside configuration file:
Create subdomain_parameter.php inside config folder.
Inside this file you have access to ther $container so you can manually retrieve current subdomain from the url and pass it to the container.
Import subdomain_parameter.php in the config.yml

Symfony translating routes using BeSimple/BeSimpleI18nRoutingBundle duplicate routes

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.

Symfony 2 dynamic routing (e.g. for stores)

I'm new at Symfony 2, now I'm trying to get a dynamic routing, I mean really dynamic.
For example:
example.com/en/categoryLevel1/categoryLevel2/categoryLevel3/productId-ProductName
OR
example.com/en/categoryLevel1/categoryLevel2/productId-ProductName
OR
example.com/en/categoryLevel1/categoryLevel2/categoryLevel3/
The number of category levels (the category depth) have to be flexible to 100%. It must be possible and able to use one level to twenty levels.
Where is the entry point to setup this (which classes are doing those routing stuff)?
Another example is:
routes on the old page:
example.com/{categoryLvl1}/{categoryLvl2}/.../p-{productId}
at the new page are some changes in the routes:
example.com/{lang}/{catLevel1}/{catLevel2}/.../{productId}-{productName}
how i do the regex, etc.. i know. But i can't find the routing process in symfony (better the pre-routing process). I would like to build an pre-routing class and fallback the "normal" symfony2 routing. i have to match old and new, both are completely dynamic.. the old one is written in ZF1 (pretty easy for me) but symfony2 is a new area for me...
Let's assume you have a bundle that handles this type of URL, you might add the following in the bundle's routing.yml (I prefer yml, YMMV).
YourSomethingBundle_main_any:
pattern: /{request}
defaults: { _controller: YourSomethingBundle:Main:dispatcher }
requirements:
request: ".*"
Important: This is a “catch-all”, letting you process the actual request path in your controller. You should either prefix the pattern path, or load this bundle after all other bundles, or other routes will no longer work.
As per SF2 conventions, you would now have a MainController class with a dispatcherAction method:
<?php
namespace Your\SomethingBundle\Controller;
use \Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MainController extends Controller
{
public function dispatcherAction($request='')
{
$request = preg_split('|/+|', trim($request, '/'));
// ... and so on.
}
}

"Name" of the route in Symfony2 relevance

I am wondering, what is the use of the "name" of the route in Symfony2 routes.yml file
_welcome:
pattern: /
defaults: { _controller: AcmeDemoBundle:Welcome:index }
For example here, pattern and defaults are obviously keywords, however, what the _welcome stands for? Is it arbitrary or a is it kind of predefined keyword for every bundle? Thank you in advance.
The route name is useful for route debugging and generating urls. You will find the route name is used extensively in Twig templates when generating links with the path() function. You can also generate urls from the route name in a controller. More information here
It is good to follow a logical convention when naming routes. Something like:
bundle_name.controller.action is a good place to start.
In this case _welcome is an arbitrary, unique id for each route you have in your project. You need it if you want to generate a url out of a template or if you want to overwrite a vendor-route...

Categories