I have a form that generates results and I would like to print the results to a new page. Currently I have an HTML form inside a node with the results sent to calc.php. calc.php is styled to look like part of drupal but is not actually inside drupal. There are no database queries involved. You can see the form and results here http://colorgenetics.info/equine/foal-coat-color-calculator

I'm trying to write a module (my very first) that will do the same thing but I haven't been able to figure out how to send the form data to a new page for processing. I found some information about using $form['#action'] but doesn't that require the php filter? I'd rather leave that off if possible. I don't mind the form data appearing in the url. In fact, I actually prefer it so that users can link to their results. What would be the best way to accomplish this?

Thank you for your time

Comments

Jaypan’s picture

First you register a menu path with wildcards for the results page:

function my_module_menu()
{
  $menu['results/%/%']
  (
    'title' => 'Form results',
    'page callback' => 'my_module_results_page',
    'page arguments' => array(1,2), // these are the wildcard positions from the path
    'access callback' => TRUE,
  );
  return $menu;
}

The above code has positions for two wildcard slots. You can add up to nine wildcards in a menu path (Drupal unfortunately doesn't allow more than that).

In your callback function you access these values as follows:

function my_module_results_page($var1, $var2)
{
  // do something here with $var1 and $var2
}

To redirect your users to this page, in your form submit function you do something like follows:

function some_form_submit($form, &$form_state)
{
  $form_state['redirect'] = 'results/' . $form_state['values']['var1'] . '/' . $form_state['values']['var2'];
}

Setting $form_state['redirect'] in your submit function will redirect the user to the given path. As you can see, I've set the path using values submitted in the form. These two values will become $var1 and $var2 in your page callback function from your menu path.

alforddm’s picture

You can add up to nine wildcards in a menu path

I would defiantly need more than 9. Currently I'm passing 24 arguments. Are their other options?

Jaypan’s picture

Two that are non-Drupal specific:

1) Use $_GET variables (append them to the end of your URL) and perform a redirect in the same manner to a different page. You can ignore the wildcards in such a case.
2) Store the values in a session variable, and perform the same redirect.

The first will allow you to link back to the results page. The second will not.

One that is Drupal specific:
Store the values in $form_state['storage'] and, rebuild the form using $form_state['rebuild'] = TRUE, and show your output on the same page as the form (by checking to see if there are values in $form_state['storage']). For an example you can see this tutorial I put together: http://www.jaypan.com/tutorial/drupal-7-ajax-driven-multi-step-forms-non...

This method will not allow you to link to the results page however.

alforddm’s picture

I feel really silly asking for help again. I was hoping to get his worked out on my own but I'm still having problems and I can't seem to find examples for what I'm trying to do online. I was going to try to just append the variables to the url like this

$form_state['redirect'] = 'canine/puppy-color-results/test=' . $form_state['values']['test'] . 'test1=' . $form_state['values']['test1'];

and then use $_GET to retrieve the values but this doesn't work however because $form_state ['redirect'] encodes the url.

If I change the form method

$form['#method'] = 'get';

The form values are in the url but then the redirect doesn't work. It just reloads the form with the variables in the url.

I did discover I can use $_SESSIONS and I can get the values I want but I wasn't sure if this was a ok or not?

Jaypan’s picture

You'll probably need to write your redirect like this:

$form_state['redirect'] = array
(
  'canine/puppy-color-results',
  array
  (
    'query' => array
    (
      'test' => $form_state['values']['test'],
      'test1' => $form_state['values']['test1'],
    ),
  ),
);

And you don't need to set the method to GET, because you are redirecting to a different page altogether, that has nothing to do with the form, and so you will not be using your GET variables in the form.

It sounds like your submit function is not being called at all, or else you would have seen a redirect. So you'll need to post your code for further assistance.

alforddm’s picture

This worked! I was able to use $_GET to retrieve the variable on the new page. *happy dance*

Can you explain why this formatting works?

Thank you so much!

Jaypan’s picture

When setting $form_state['redirect'], you can either pass a string, which is a path, or if you need something more complex, you can pass an array like I've shown. You can read the documentation on the url() function for more information about allowable values.

alforddm’s picture

Thanks so much for responding. I've looked through some of your tutorials and found several of them helpful.

I've run into a problem

Here is my code

function caninecolorcalc_menu() {
   $items = array();
  $items['canine/puppy-color-calculator'] = array( //this creates a URL that will call this form at "examples/form-example"
    'title' => 'Puppy Coat Color Calculator', //page title
  //  'description' => 'A Calculator that determines chances of a puppies genotype based on sire and dams genotype ',
    'page callback' => 'drupal_get_form', //this is the function that will be called when the page is accessed.  for a form, use drupal_get_form
    'page arguments' => array('caninecolorcalc_form'), //put the name of the form here
    'access callback' => TRUE
  );
 $items['canine/puppy-color-results'] = array(
    'title' => 'Puppy Coat Color Results',  
            'page callback' => 'display_puppy_results',
            'access callback' => TRUE );
  return $items;
}
 function caninecolorcalc_form($form, &$form_state) {
  $form = array();
//  $form['#action'] = url('canine/puppy-color-results');
 // $form['#method'] = 'post';
  $form['test']= array(
    '#type' => 'textfield',
    '#title'=>  t('test'),
    );
  $form['submit'] = array(
    '#value' => 'Submit',
    '#type' => 'submit',
    );
  return $form;
}
function caninecolorcalc_form_submit($form, &$form_state ) {
  $form_state['redirect'] = 'canine/puppy-color-results';
}
function display_puppy_results()
{
    echo "at least we got here";
  
}

It will redirect to a the desired page but the page isn't themed at all. It's a blank white sheet with "at least we got here". I also tried using

 function caninecolorcalc_form($form, &$form_state) {
  $form = array();
 $form['#action'] = url('canine/puppy-color-results');
$form['#method'] = 'post';
  $form['test']= array(
    '#type' => 'textfield',
    '#title'=>  t('test'),
    );
  $form['submit'] = array(
    '#value' => 'Submit',
    '#type' => 'submit',
    );
  return $form;
}

and leaving out the submit function but I get the same results. What am I missing?

Jaypan’s picture

You should very rarely change the #action on a form, if ever. So don't go with that option.

Your other issue was that you were echoing a value. You only ever do that in template files. You return values from page callbacks. Change your echo to return, and the page will be themed.