Symfony generate incorrect url with double / - php

I'm working on a symfony3 project, and i'm stuck with a problem,
We are sending emails that are twig based, with a button that has a link to our platform.
Button example
And the open document button link is the following one:
app.example.com/books/bookId/pageId
Which is generated through twig:
url("open_book", { bookId: book_id, pageId: page_id })
And the url is defined on a controller file, with annotations
#Route("/book/{bookId}/{pageId}", name="open_book")
So, the link that user gets on the email, is the original, but with double // before books, like this:
app.example.com//books/bookId/pageId
I'm working on last twig version, and I don't know if it can be symfony issue either, since its only happening on our prod environments (it works on local, yey)
If it helps, our routing.yml
app:
resource: "#BooksBundle/Controller/"
type: annotation
prefix: /
host: app.%host%
This is only happening with urls that are generated by twig. We are using jms translation and jms i18n bundles also, so I thought maybe its trying to set a null locale betwen / / like:
app.example.com/en/books/bookId/pageId
But instead of en, an empty language maybe.
Any idea to start with?
UPDATE 3/01/18
Hey! Thanks for all answers. It seems that was a problem with symfony configuration at the end...
On file parameters.yml:
router.request_context.scheme: '%env(ROUTER_REQUEST_CONTEXT_SCHEME)%'
router.request_context.host: '%env(ROUTER_REQUEST_CONTEXT_HOST)%'
router.request_context.base_url: '%env(ROUTER_REQUEST_CONTEXT_BASE_URL)%'
Then our value for base_url was /. Seems that was the real problem. Removing / on that param does the trick.
Thanks!!

For every route in the controller you are using prefix /:
app:
resource: "#BooksBundle/Controller/"
type: annotation
prefix: /
host: app.%host%
This means that every route like:
#Route("/book/{bookId}/{pageId}", name="open_book")
Will be prefixed with /. In the end this route path will be //book/{bookId}/{pageId}. Some libraries truncate path values, the other ones not.
So just remove prefix parameter completly or declare route's path without leading slash:
#Route("book/{bookId}/{pageId}", name="open_book")

try to replace this line
url("open_book", { bookId: book_id, pageId: page_id })
By
url("open_book", { bookId: book_id, pageId: page_id }) | replace({'//': "/"})
OR
{{ app.request.schemeAndHttpHost }} {{ path("open_book", { bookId: book_id, pageId: page_id }) }}

Related

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

Change routing basing on language, translate URL parts

Is it posible in Symfony 1.2 to change routing basing on lang?
In my system there are 2 langs - EN, PL
Sample route look like this:
produkt_show:
url: /products/:pslug/:idslug
param: { module: product, action: show }
What I want to achieve: I want produkt_show route to match [and generate] different url depending on the current language. So in PL my url would look like this:
/produkty/:pslug/:idslug
It is essential those routes to have the same names. I can't change all url_for/link_to etc. calls and pass different routes names to them.
If anything is unclear -please, ask ahead.
UPDATE
according to the advice of j0k I used plugin. I choosed zxI18nRoutingPlugin. It seems to partialy work - it resolves url to right route if I write it literally in browser address input. But it still generates URLs that are not translated.
e.g.
my route:
contact_form:
url: /contact_form
param: { module: contact_request, action: new}
trans unit:
<trans-unit>
<source>contact_form</source>
<target>formularz-kontaktowy</target>
</trans-unit>
generated url:
Kontakt
But if I type BASE_URL/formularz-kontaktowy - right action is executed.
This is my configuration from dev toolbar:
Request:
parameterHolder:
action: new
module: contact_request
sf_culture: pl
attributeHolder:
sf_route: 'sfRoute Object()'
User
options:
auto_shutdown: false
culture: pl
default_culture: pl_PL
use_flash: true
logging: '1'
timeout: 10800
attributeHolder:
symfony/user/sfUser/attributes: { LAST_CATEGORY_ID_PATH_VAR: null, product_elements_on_page: 50 }
culture: pl_PL
I just can't figure it out, I would appreciate any help, suggestions, anything, because I'm stuck with this.
UPDATE 2
factories.yml:
all:
routing:
# class: sfPatternRouting
# param:
# generate_shortest_url: true
# extra_parameters_as_query_string: true
class: zxPatternI18NRouting
param:
generate_shortest_url: true
extra_parameters_as_query_string: true
use_cultures: [pl, de, en, ru] # destination cultures. Plugin looks for translations for these cultures.
culture_into_url: false # defines if culture should be always placed in url
There are some plugins that can handle such case (or at least gave you a way to do this on your own):
zxI18nRoutingPlugin
The zxI18nRoutingPlugin extends sfPatternRouting class giving possibility to translate routes patterns static text to different languages.
gbI18nRoutePlugin
Easy way to have I18N Routing.
An other option can be to add the culture inside the route, like /pl/product, /en/product, etc ..

Url encode a dot (.) in URL?

Currently I am doing a small code in symfony that will cause url have resource like this:
http://url/val/abc.abxhd
I was able to get the parameter abc successfully from http://url/val/abc, but when I try to run the URL of http://url/val/abc.abxhd. Symfony simply throw a 404 error.
What could be the problem here. the URl are written using rawurlencode also.
group:
url: /group/:group
param: {module: group, action: show}
requirements:
sf_method: [get]
Actually symfony was finding dot (.) as a segment separator. This is the reason why in my case it cannot find the route. After Add the ff to my route. it works just like expected:
group:
url: /group/:group
param: {module: group, action: show}
requirements:
sf_method: [get]
options:
segment_separators: [/]
Seems like Symfony doesn't like dots . in urls : http://groups.google.com/group/symfony-users/browse_thread/thread/65d928b601bff9f4/096af0fcc478997b?pli=1
Users provide several tips and solutions.
What you can do is to handle this with url rewriting (as suggested in the thread) but take care not to rewrite files (meaningly: http://url/folder/myjquery.js)

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: .+

link_to() generates route successfully, but clicking on that link results in a 404

I've set a website up. If I try and click on a link such as register I get the following error:
404 | Not Found | sfError404Exception
Empty module and/or action after parsing the URL
"/trevelyan.alumni/register" (/).
The links are generated using
<?php
print link_to( 'Register', 'register/index' );
?>
And I have a 'register' module in apps/frontend/modules/register.
I'm quite new to Symfony, any help is appreciated!
routing.yml:
# default rules
homepage:
url: /
param: { module: home, action: index }
default_index:
url: /:module
param: { action: index }
default:
url: /trevelyan.alumni/:module/:action/*
I think that your problem is that you're running symfony out of a "sub-site" instead of directly off of the "root" url (http://www.dur.ac.uk/trevelyan.alumni instead of http://www.dur.ac.uk/). I think the easiest solution would be to add trevelyan.alumni to the front of all your urls in routing.yml.
For example, for the default route, instead of
default:
url: /:module/:action/*
use
default:
url: /trevelyan.alumni/:module/:action/*
Read Steven Oxley, but try this as well :
Check you have at least an action class in your module dir with the proper name (symfony is case sensitive, and this is very tricky).
If you do, check that the default action (in the module config files) is one of the action class in your module.
Don't forget to clear cache every time you change a config file.
I managed to fix this by editing the symfony controller files to use the $_SERVER variables to pick a module from, if one was not found.
at the end of your routing.yml file:
homepage:
url:
param: { module: main, action: index }
default:
url: /:module/:action/*
and donĀ“t forget to clear the cache afterwards ;)
Just a quick note, for the routing change(s) to take effect, you must run symfony clear cache:
./symfony clear-cache
you should remove a dot from your matching url for route because of default routing rules
change your default route to:
default:
url: /trevelyan_alumni/:module/:action/*
and that should work. note that dot(.) is replaced with _
I had upgraded from symfony 1.2 to 1.4, and was having this problem. At the end of the day, basically the config files have all changed enough to the point that routing somehow broke. Going through the app config files and comparing / updating them against the "new app" templates found in lib/vendor/symfony/lib/config/config (or where ever you are keeping symfony) fixed this issue.

Categories