Enrique Moreno Tent
Enrique Moreno Tent

Reputation: 25317

Slugs not working in Forms with GET method

This is my routing:

myapp_upgradeAccount:
    path:  /upgradeAccount
    defaults: { _controller: myapp:UpgradeAccount:index }

myapp_checkUsernameForUpgrade:
    path: /upgradeAccount/check/{username}
    defaults: { _controller: myapp:UpgradeAccount:checkUsername }
    methods: [GET]

and this is my form

<form method="get" action="upgradeAccount/check">
    <label for="username">Insert your username:</label>
    <input name="username" type="text">
    <input id="chech-username-for-upgrade" class="green" type="submit" value="Check">
    ...

But everytime I submit the form I get this error:

No route found for "GET /upgradeAccount/check"

The problem is that when I submit the form, I get the following URL:

http://localhost/app_dev.php/upgradeAccount/check?username=123

when i think I should be getting

http://localhost/app_dev.php/upgradeAccount/check/123

If I trz the latter manually, it works allright. What am I missing?

Upvotes: 0

Views: 1036

Answers (3)

cheesemacfly
cheesemacfly

Reputation: 11772

This is the way HTML forms work.
From w3.org:

get: With the HTTP "get" method, the form data set is appended to the URI specified by the action attribute (with a question-mark ("?") as separator) and this new URI is sent to the processing agent.

To do what you want to do keeping the GET method, you have to define your route as:

myapp_checkUsernameForUpgrade:
    path: /upgradeAccount/check
    defaults: { _controller: myapp:UpgradeAccount:checkUsername }
    methods: [GET]

And in your controller, you access the query string parameter with:

if(!is_null($this->getRequest()->get('username'))
{
  //Do your stuff
}

EDIT:

If you want your user to be redirected to a url formatted as upgradeAccount/check/{username}, you can either do it with JavaScript (as suggested in @usoban answer) or inside the controller using Redirect:

//path:  /upgradeAccount/check
public function check()
{
  if(!is_null($this->get('request')->request->get('username')))
    return $this->redirect($this->generateUrl('myapp_checkUsernameForUpgrade', array('username' => $this->get('request')->request->get('username'))));

  //By default, return the view with your form asking the username
  return $this->render('AcmeHelloBundle:Hello:index.html.twig');
}

//path: /upgradeAccount/check/{username}
public function checkUsername($username)
{
  //Do some fun stuff with $username coming from the url
}

Then in your view, the form signatures becomes:

<form method="post" action="upgradeAccount/check">
  <label for="username">Insert your username:</label>
  <input name="username" type="text">
  <!-- additionnal fields -->
  <input id="chech-username-for-upgrade" class="green" type="submit" value="Check">
</form>

And your route:

myapp_check:
    path: /upgradeAccount/check
    defaults: { _controller: myapp:UpgradeAccount:check }
    methods: [POST]
myapp_checkUsernameForUpgrade:
    path: /upgradeAccount/check/{username}
    defaults: { _controller: myapp:UpgradeAccount:checkUsername }
    methods: [GET]

Upvotes: 2

usoban
usoban

Reputation: 5478

As @cheesemacfly mentioned, that is how forms work :)

To get it woking myself, I used some javascript. Let's assume you're using jQuery:

<form method="get" action="upgradeAccount/check/___username___" id="my_form">
...
    <input name="username" type="text" id="username">

$(document).ready(function(){
  $('#my_form').submit(function(evt){
      var username = $('#username').val(),   
          action   = $(this).attr('action').replace(/___username___/g, username);

      if (/* empty or whatever 'validation' */) {
        evt.preventDefault(); // stop the form from submitting
        return false;
      }      

      $(this).attr('action', action);
      return true;
  });
});

Upvotes: 0

Kris
Kris

Reputation: 6122

You need to generate routes that take parameters. so you would need to do

<form method="get" action="{{path('your_route_name', {username:'usernmae'})">

However this obviously won't quite work for you since you do not know the username until they enter it. You could look into the FOSJsRoutingBundle but this will require javascript. Not the best solution, but it will work. Otherwise you will need to remove the username parameter

Upvotes: 0

Related Questions