I'm setting up FOSRestBundle and have some doubts, don't know if related to Symfony2 Routing component or can be done in any other way. Here,
1) How do I check if X-PDONE-SESSION-ID is set on request headers before execute the method? Can this be done using annotations on routing? Any ideas on how to check that?
2) I need to use this RegEx \b(?:(?:https?):\/\/|www\.)[-a-z0-9+&##\/%?=~_|!:,.;]*[-a-z0-9+&##\/%=~_|] as requirements in the route #QueryParam(name="token", requirements="") for check valid URLs, how?
I have read here and here but wasn't helpful at all.
(1) can be done using the method described in the book article you referenced as not being helpful:
As you've seen, a route can be made to match only certain routing wildcards (via regular expressions), HTTP methods, or host names. But the routing system can be extended to have an almost infinite flexibility using conditions:
contact:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contact }
condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
The condition is an expression, and you can learn more about its syntax here: The Expression Syntax. With this, the route won't match unless the HTTP method is either GET or HEAD and if the User-Agent header matches firefox.
In (2), you show a regex for a complete URL and not just a query parameter. It isn't possible to change the whole regex used by the Routing component by default as far as I know.
Related
currently, I'm trying to implement a few routes to symfony 2.5 that lead me to a little problem. I need to have an url scheme that has the same route depending on a custom service.
route_category:
pattern: /{location}/{category}
defaults: { _controller: LocationBundle:Category:index }
condition: "service('location_category_service').isCategory(request.get('category')) == true"
route_merchant:
pattern: /{location}/{merchant}
defaults: { _controller: LocationBundle:Merchant:index }
condition: "service('location_merchant_service').isMerchant(request.get('merchant')) == true"
What I want symfony to do is:
Given URL path: /germany/restaurants
try matching route 1
"isCategory" returns true, so this route matches
Given URL path: /germany/aldi
try matching route 1
"isCategory" returns false, so we skip this route
try matching route 2
"isMerchant" returns true, so this route matches and we execute the MerchantController
Given URL path: /germany/this-does-not-match-anything
try matching route 1
"isCategory" returns false, so we skip this route
try matching route 2
"isMerchant" returns false, so we skip this route
... now we can execute the default behaviour when no route matches
I thought, that the condition would exactly does what I want, but I only have the requestContext and the request in the expression language, not the service container.
Does anybody know, how I can inject the service container to the expression language for routing purposes or maybe something else that would help to solve this problem?
Thanks in advance :-)
Having two variables like this is troublesome. From experience the best practice is to separate these two with a static value like so:
route_category:
pattern: /{location}/category/{category}
route_merchant:
pattern: /{location}/merchant/{merchant}
Otherwise as David Kmenta said you will be writing extra code trying to figure out what is what.
Ask yourself if that type of coding is worth having one less extra word in your urls?
To add to this, think of your users: if you have a merchant that sounds like a category will they know the difference or will the scheme you're after just confuse them.
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...
I'm trying to create a url with annotations of the route.
The problem is that I can write any URL large, small or different.
#Route("/{staat}/", name="showStaats",requirements={"location" = "berlin|bayern|brandenburg"})
This URL can be accessed both from www.example.com/berlin and under www.example.com/Berlin.
I would, however, that it is attainable only under www.example.com/berlin.
Answering the question "How to make case-insensitive routing requirement":
You can add case-insensitive modifier to requirement regexp like so:
(?i:berlin|bayern|brandenburg)
You have "/{staat}/", but your requirements set "location" = ..., these should match, so maybe that's the cause of your problem.
If you don't want to hardcode the list of states in your route, you could inject a service containter parameter with a list of states. Just see How to use Service Container Parameters in your Routes in the documentation for how to do that.
If you just want to check, whether that state is all lower-cased you could try the following requirement:
staat: "[a-z-]+"
This should match only lowercase characters and dash (e.g. for "sachsen-anhalt"). But I'm not entirely sure if this will work as the router's regex-detection is a bit quirky.
You could also create a custom Router Loader which will create routes programmatically, e.g. by fetching the list of states from a database or file.
edit:
As I wrote in my comment I would add the list of params as a Service Container parameter, e.g. %my_demo.states% containing a list of states. I'm not sure however if this will work with annotations. So here is a quick workaround how to get it working.
In your app/config/config.yml you append the %my_demo.states% parameter:
my_demo:
states: ["berlin", "brandenburg", "sachsen-anhalt", ... ]
In your app/config/routing.yml there should be something like this:
my_demobundle:
resource: "#MyDemoBundle/Controller/"
prefix: /
type: annotation
The type: annotation and #MyDemoBundle is the relevant part. Add the following route before this one, to make sure it takes precedence:
showStaats:
path: /{state}
defaults: { _controller: MyDemoBundle:State:index }
requirements:
state: %my_demo.states%
This will add a route which will apply before your annotations using the list of states as parameters. This is a bit crude, as you are mixing yml/annotation-based routing, but it's imo still better than cramming a list of 16 states in the annotation, not to mention its easier to maintain.
I heve an embedded controller in my base template. It's a search bar.
For the search bar controller, I have a route "myProject/search".
What I would like is that this route will be taken only when the template where I am embedding the controller (base.html.twig) will call it, and not when i manually put in the browser: "myproject/search".
Any idea on how to do that.
I think, since some time you can't do it:
http://symfony.com/doc/current/book/templating.html#embedding-controllers
quote from the docs:
Even though this controller will only be used internally, you'll need
to create a route that points to the controller
(...)
Since Symfony 2.0.20/2.1.5, the Twig render tag now takes an absolute
url instead of a controller logical path. This fixes an important
security issue (CVE-2012-6431) reported on the official blog. If your
application uses an older version of Symfony or still uses the
previous render tag syntax, you should upgrade as soon as possible.
Anyway, I guess, you can try do it yourself by passing some "secret" argument to search action when you call it from your template. Next in the action you check if the argument was passed to it, and if not you throw 404.
Another way to achieve your goal is use .htaccess file.
You can restrict your route to a certain method by _method option in your routing configuration:
your_rote:
pattern: /myProject/search
defaults: { _controller: YourBundle:YourController:YourAction }
requirements:
_method: POST
I know how these kind of URLs load the page ... based on their GET parameter.
http://www.bedupako.com/songs.php?page=show_song_details.php&songid=1167&n=0&back=no
and in the back-end roughly something like this:
<?php
switch($_GET['page']) {
case 'xx': include('my page');break;
.
.
.
default: include('default');break;
}
?>
But how do these kinds of URLs work? I mean, how is the data loaded dynamically?
www.dummysite.com/parm/subpage1/xyz
www.dummysite.com/parm/subpage2/xyz
How are these parsed similar to the GET param like websites?
In most cases this will be handled by the web server on-the-fly according to a set of rules. The specifics of it will vary from server to server and on a case-by-case basis. In Apache it is usually done using the mod_rewrite extension.
You can use mod_rewrite by itself as others have suggested, but most sites do not do this because its not very flexible, and can be annoying to maintain if you have more than a couple of these "pretty" URLS.
Instead they set up a basic rewrite rule to forward everything to a single index.php and then on the application side they parse the URI based on defined patterns - these are called "routes". Route parsing usually happens in some kind of routing class which process the defined routes and compares them to the URI, and then when it finds a match parses out the parameters for the matched route.
These all provide good examples of a router, but they are hard to understand without the other interacting classes:
Zend: Zend_Controller_Router_Rewrite
Symfony: sfPatternRouting
Cake: Router
CodeIgniter: CI_Router
You should look at http://httpd.apache.org/docs/2.0/misc/rewriteguide.html url rewriting if you're with apache (most likely)