Hi guys, I'm implementing a hook_form_alter in one of my modules. But the form I'm altering has a form['#action'], which points to a URL.
I would like to call my submit function, so I did this: $form['#submit'] = array('accesscustom_submit'); then I wrote the "accesscustom_submit()" function.
This doesn't seem to work. Any help is appreciated. Thanks-

Comments

roper.’s picture

Try setting $form_state['redirect'] = 'path/to/redirect'; in your submit handler.

Also, when you're altering an existing form, you should ADD your submit function to the array instead of replacing it. The way you have it now will prevent the original submit handlers from running (which is sometimes desired, but usually not). Try this instead, if you want to append your submit function:

$form['#submit'][] = 'accesscustom_submit';

:)

bertomart’s picture

Hi roper. - thanks a lot. I set 'redirect' but it didn't work. The original form has a '#action' property, set to a url. Each time I submit, it goes to that url. Is it ok to have both '#action' and '#submit' properties? (don't see why this shouldn't be ok). Thanks for the tip about '#submit'.

bertomart’s picture

It actually worked when I remove the form['#action']. I think this property (in the form I'm trying to modify) is preventing my submit function from being called. Any ideas how to allow my function to be called before '#action'? - much thanks-

vasanthanand’s picture

i am also facing the same issue so how did you allowed both form action and form submit then

sunwin’s picture

in your form add this:

$form['save'] = array(
'#type' => 'submit',
'#value' => t('save this content'),
);

then you can define:
function yourmodule_submit($form, &$form_state) {}

hope can help you!

bertomart’s picture

got it to work. thanks sunwin

roper.’s picture

Wait, WTF, that's not necessary nor preferable. There's no need to define your own (nor override) the actual submit button itself.

Simply doing this should work, perhaps you weren't passing $form and &$form_state in your submit function from the original post?

...
$form['#submit'][] = 'my_submit';
...

function my_submit($form, &$form_state) {
  $form_state['redirect'] = url('path/to/redirect');
}

Although, if the ONLY thing you're trying to change about this form's submission workflow is the redirect (ie there's no other logic you need to run besides that), then you can just override $form['#redirect'] = 'path/to/redirect'; in your form_alter and you don't need a submit handler IIRC.

malinica’s picture

Hi, I am trying to do something very similar so please bare with the question as I am pretty new to Drupal. I am using a custom module (webform) form to grab user information and I need to redirect it, i.e. modify its action to an external third-party link. Basically, I need to grab all the data from the form and pass much of it as hidden variables to the third party link. I have created a custom module and am working with the appropriate hooks. I have updated both hook_form_alter and have created a handler to redirect the submit to my third party url. I have figured out a way to access the form values in the handler by calling pieces of the $form_state['values']. However, I don't know how to get the the action to change to the external URL on this modification. I have the following

function my_module_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
    case 'my_form_id':
    $form['#submit'] = array('my_module_node_form_submit_handler');
    //the form action isn't set anywhere yet (its blank on a var_export)
      break;
  }
}

function my_module_node_form_submit_handler($form, &$form_state) {

    $form['#action'] = 'my link';
    $form_state['values']['LOGIN'] = 'test';
    $form_state['values']['PARTNER'] = 'test';
     ....
}

The above sadly fails. I.e. the form does not change its action. I have tried $form_state['redirect'] but that doesn't seem to work. If I set the action in the hook_alter the changes made to the variables in the handler do not take (which is not what I want). I need to modify the action of the form after the changes made in the handler. Thank you for your help!

roper.’s picture

You can't modify the #action from within the handler, because the form has already been submitted to the #action URL at this point.

What you need to do is issue an HTTP POST from within your submit handler.

function my_submit_handler($form, &$form_state) {
  // Make an array of values to pass to 3rd party.
  $pass_these = array();
  $pass_these['whatever_they_call_this_field'] = $form_state['values']['whatever_you_call_it'];
  $pass_these['whatever_they_call_this_other_field'] = $form_state['values']['whatever_you_call_it_instead'];

  // Post the data to 3rd party.
  $url = 'http://example.com/accept-my-shiz';
  $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
  $data = drupal_query_string_encode($pass_these);
  drupal_http_request($url, $headers, 'POST', $data);
}

Keep in mind that this means every post you do from this form is ultimately doing 2 POSTs and is dependent on the response-time of the server you're sending the request to.

rashid5855’s picture

Hi, Where we need to create this custom handler of if they already created, where can i found those. I need to sent form data to rest API after form submission

incaic’s picture

How did you get it to work? I am not able to get the hook_submit function to be called.

I have the following in a custom module:

function my_form(&$form_state) {
  $form= array(
    '#action' => '/path',
    'submit' => array(
      '#type' => 'submit',
      '#value' => t('Save'),
      //'#submit' => array(my_form_submit), // doesn't work with or without this.
    ),
    //'#submit' => array(my_form_submit),   // doesn't work with or without this.
  );
  return $form;
}

function my_form_submit($form, &form_state) {
  // ... debug prints
}

I call the form within a block with the following:

  print drupal_get_form('my_form');
roper.’s picture

Why are people trying to change the #action..?

The #action is the URL to which the form data is POSTed on form submission. By default it is the current path. This URL needs to have logic to deal with the POST data (ie, your submit handler).

By changing the #action, you're changing where the POST is sent, and your submit handler isn't going to be called on that path.

What is your goal? To control where the user goes when they submit this form? If so, set #redirect, not #action. If your goal is to submit this data to another URL, you have to do an http POST in your submit handler, like I showed in my last comment.

incaic’s picture

Thanks roper for your reply.

I need to run some logic on the posted data and redirect to another page, but didn't want to post to the current path then do a redirect, so was wondering if there was a way to post to another page and have that page execute that logic before the page is rendered.

Apparently this is not possible the way I did it.

What would you suggest?

Thanks.

roper.’s picture

Just set #redirect on your $form. Your submit handler will be called, executed, and then will redirect all behind the scenes. It's not going to cause 2 pageloads or anything...

Basically, when you submit a form, drupal_process_form() is called, which runs the validation/submission handlers, and then sends you to a new page if you supply a redirect.

incaic’s picture

Thank you for sending me in the right direction with drupal_process_form().

I found the following to be true. The current page (action path) gets called therefore drupal gets initialized. After that drupal_process_form() gets called and if #redirect is set a drupal_goto() is called.

I suppose one way to avoid that extra drupal initialization would be to point action to /path/to/redirect then check for POST data in my custom module's init function and behave appropriately.

If there is any other way to do this, please share.

Thanks.

incaic’s picture

[SOLVED]

For some background, I have a search form connected to Acquia Search at /search/apachesolr_search and so whenever a POST or a GET is performed on that path there is a lag. In that form I have two buttons one that performs the search and stays on the same page and one that simply saves the data in the form and redirects to a new page. There is no need to perform a search (communicate with Acquia Search) when clicking the save button, which was happening because form validation and submit functions are called after menu page callbacks.

The solution I went with is to put a wrapper around the existing page callback function for /search/apachesolr_search as the following:

function myModule_menu_alter(&$menu) {
  $menu['search']['page callback'] = 'myModule_search_view';
  $menu['search/apachesolr_search']['page callback'] = 'myModule_search_view';
  $menu['search/apachesolr_search/%menu_tail']['page callback'] = 'myModule_search_view';
}

function myModule_search_view($type = NULL) {
  // logic can check POST and/or GET data
  // and act approriately
  if ($redirect_to_newpage) {
    $query = array('nid',$nid);
    drupal_goto('path/to/newpage',$query);
  } else {
    return apachesolr_search_view($type);
  }
}

I was able to cut my load time with this.