I am sure this is probably a pretty easy question, but I can't seem to find the answer. I am using Drupal 6 and would like a form to go to another page when submitted. So I am using redirect. But I want to specify a query string, and my question mark gets encoded. How do I stop this?


$form_state['redirect'] = "purchased.html?list=1";

But this results in the following URL:


How do I tell it to leave my question mark and equals sign alone?



kenuck’s picture

Hi Jeff,

Have you tried the url() function? http://api.drupal.org/api/function/url/6
You'll probably want to use the 'query' $options.


http://www.netrift.com - Custom modules
http://ulisting.netriftsolutions.com - Drupal Real Estate Module for Drupal 6
http://drupal.org/project/friend - Social Neworking for Drupal 6

jeffheaton’s picture

I tried that. It looks the url function is just a handy function to generate a URL string. Which has a question mark in it as well. It just returns a string. So Drupal formats the question mark returned by the url function just the same as if I had written the question mark myself. There has to be a way to tell drupal to not URL encode the string you are passing it on the "redirect" option.

jeffheaton’s picture

Ah hah! I found a way. Don't use


Instead use drupal_goto, which has options for a query string.

Ericmaster’s picture

this will work only if you don't need to process anything after the drupal_goto call is done, that is you don't have any other submit handler after the one calling the drupal_goto

markpape’s picture

Thanks Jeff! Your post, although old, lead me to a different solution. It took me many hours to discover, i looked at changing the $form["#action"],$form_state['redirect'] or doing a" hook_form_alter" but couldn't get those to work.

I needed to change the url redirected to AT VALIDATION FAILURE, not the submission redirect i.e. $form_state['redirect'].

Here is an example of code that could be used:

function MY_MODULE_form_validate($form, &$form_state) {
// Start Date should not be older than 6 months
        $start = strtotime(str_replace('/', '-', $form_state['values']['date_start']));
$six_months_ago = strtotime("-6 months");
        if ($start < $six_months_ago) {
            form_set_error('date_start', t('Your start date cannot be earlier than 6 months.'));
            drupal_goto('documents/search',array('query' => array('p' => '0')));
markpape’s picture

What i should also mention here is that using drupal_goto became key for me to be able to open accordions holding different forms on the same page. Being able to set the validation failure url to documents/search?p=0 meant that the following accordion code would fire and thereby make the form concerned visible to the user on the same page being viewed which was documents/search . #mapAccordion was my selector.

(function ($) {
    function getParam(name) { 
      var query = location.search.substring(1); 
      //console.log("getParam : query: "+query);
      if (query.length) { 
          var parts = query.split('&'); 
          for (var i = 0; i < parts.length; i++) { 

            var pos = parts[i].indexOf('=');
            //console.log("getParam : parts["+i+"]: "+parts[i]);

            if (parts[i].substring(0,pos) == name) { 
              return parts[i].substring(pos+1); 

        return false; 

      function getPos(hash) { 
      var query = location.search.substring(1); 
      //console.log("getPos : query: "+query);
      if (query.length) { 
          var parts = query.split('&'); 
          for (var i = 0; i < parts.length; i++) { 

            var pos = parts[i].indexOf('=');
            //console.log("getPos : parts["+i+"]: "+parts[i]);

            if (parts[i].substring(0,pos) == hash) { 
              return parts[i].substring(pos+1); 

        return false; 
    $(document).ready(function () {

        $(function () {
          var defaultTab = parseInt(getParam('p'));
          var pagePos = getPos('pos');
          //console.log("root for #mapAccordion : defaultTab: "+defaultTab);
          //console.log("root for #mapAccordion : pagePos: "+pagePos);
                collapsible: true,
                //active: false,
                //activate: function (event, ui) {
                //    for (var i=0;i<maps.length;i++) {
                //    google.maps.event.trigger(maps[i], "resize");
                //    center_map(maps[i]);
                //    }
            $( "#mapAccordion" ).accordion( "option", "active", defaultTab );
            if (pagePos!=false){
              window.location.hash = pagePos;


just_fixed_it’s picture

use an array?

NaX’s picture

Yup, if its an array it gets passed into drupal_goto like this call_user_func_array('drupal_goto', $goto);.

To see how your array should work just look at the docs for drupal_goto() and match your array to its arguments.

If anybody is interested here is an example taken from the docs.


$form_state['redirect'] = array(
    'query' => array(
      'foo' => 'bar',
    'fragment' => 'baz',

and for D6

$form_state['redirect'] = array(
  'abc=123&foo=' . rawurlencode($form_state['values']['bar']),


$form_state['redirect'] = array(
    'abc' => '123',
    'foo' => $form_state['values']['bar'],

FYI to everybody talking about using drupal_goto. You should never use drupal_goto directly in a form submit function, you will be cutting off all other modules that might have added their own submit handler and that runs after your function. That is why Drupal Core provides the redirect form state option so that redirecting can happen after all form processing has completed.

anou’s picture

This the solution!
Thanks a lot.


kapadokis’s picture

I think the only way to do that properly is .htaccess with the rewriterule

Jaypan’s picture

Incorrect. See the post above yours by naX for the method to do it.

artiprasad’s picture

You can use this by .httaccess file

first find this line of code in .htaccess file
#RewriteBase /drupal

replace it with following line of code:
RewriteBase /~yoursitename/yoursitename

Remove # from the code. Here "yoursitename" is the folder name after domain name like example.com/~yoursitename/yoursitename

artfulrobot’s picture

The comment above suggest the 2nd param should be an array of key-value pairs for the query string, but this does not work (in D7, at least). The Form API redirect uses url() so the 2nd argument is an options array.

i.e. the correct calling would be ('scuse short array syntax, but it's so much cooler :-D)

$form_state['redirect'] = [
  [ 'query' => [
    'list' => 1,


nitin.k’s picture

It`s pretty handy.

URL function

aryashreep’s picture

url('some/path', array('query' => array('copy_txt' => 'me')));
It will work for you.