Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
I have a simple form that includes an "#action" element. It won't validate. It doesn't even hit the hook_validate function I've written for it. When I comment out the "#action" element in the form, the form validates when "submit" is clicked. Here's the code:
function lesspaper_batch_og() {
drupal_set_message('In lesspaper_batch_og ');
$form_id = 'lesspaper_batch_og';
$form = array();
$form['#multistep'] = TRUE;
$form['#action'] = url('admin/settings/lesspaper/batch_og/confirm');
$form['go'] = array(
'#type' => 'checkbox',
'#title' => t('Go')
);
$form['#validate'] = array('lesspaper_batch_og_validate' => array($form_id, &$form));
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Continue'),
);
return $form;
}
function lesspaper_batch_og_validate($form_id, &$form) {
drupal_set_message('Form validation');
// Doesn't get here unless I remove the "#action" element from form
}
function lesspaper_batch_og_submit($form_id, &$form) {
drupal_set_message(t('Submitted.'));
}
The "#multistep" form element doesn't seem to make any difference at all.
Is this a bug, or is it by design?
Comments
Comment #1
Reg CreditAttribution: Reg commentedI just noticed the same thing with the submit hook. Comment out #action and it works fine. Oops, this for a client with the older 4.7, don't know if it's still an issue in 5.x.
Comment #2
SomebodySysop CreditAttribution: SomebodySysop commentedYes, it appears to still be an issue in 5.7 unless I'm missing something. I need the "#action" element in order to process my form correctly.
Comment #3
Reg CreditAttribution: Reg commentedI don't think this is a bug. I think it was a lack of understanding of the form module. If you redirect then you the page that you have the function on does not get loaded. Since it is not loaded the function doesn't exists and hence doesn't get called. The solution is to put the redirect in the my_module_submit as such:
This worked for me and I can't believe it's a bug since as far back 4.7 because it's too fundamental of a module for such a glaring problem to be ignored. So, I can only assume it was our lack of understanding. Because of this I am changing the settings for this post.
Comment #4
gregrenner CreditAttribution: gregrenner commentedGreetings,
I too have used the drupal_goto() to submit the form values to a remote address. While its not ideal, in my humble opinion, it does work. However, I have problems with this method because it is only good when the receiving end of the submitted form is using the GET method. Unless I'm misunderstanding the intricacies of drupal_goto(), you can't POST $form_values using drupal_goto().
A real life example:
I have a credit card payment form on www.example.com. This form's #action is "https://www.payment_gateway.com" and the #method is POST. Obviously, I want to make sure the person's name was entered, run a regex on the CC number, make sure they chose an expiration date, etc. before sending it off to the payment gateway. But because of this blind spot in Form API (or my misunderstanding it's capabilities), the end user can just hit submit with invalid or non-existent information and then are presented with less that friendly error messages from the payment gateway. I need to be able to POST $form_values to a remote address specified in #action, but only AFTER hook_validate has done it's job and given the blessing to proceed.
I realize that I could use JavaScript to run validation, but this isn't as reliable or secure as server side validation, of course. I suppose I could remove #action in order to use hook_validate, then submit $form_values to the payment gateway in a different function altogether, but like Red said... 'it's too fundamental of a module for such a glaring problem to be ignored.'
Its quite possible that I'm missing something, but it seems like this is a pretty huge hole in the Form API. Rather than a workaround, shouldn't validation be called every time a submit button is clicked, regardless of #action? I haven't found much on drupal.org, api.drupal.org, groups, etc. about this topic. Is there a patch out there for this? Is there a really good reason validation is ignored when #action is present?
Thanks,
~Greg Renner
Comment #5
SomebodySysop CreditAttribution: SomebodySysop commentedYes, and that was my next question. If I use drupal_goto in my submit:
How do I get the submitted $form_values over to 'page to redirect to'?
Comment #6
gregrenner CreditAttribution: gregrenner commented@SomebodySysop
Something like this:
But, again, this will only work if 'node/123' is looking for GET values, POST values can't be sent through drupal_goto().
~Greg Renner
www.gregrenner.com
Comment #7
gregrenner CreditAttribution: gregrenner commentedSo, now I'm confused. I'm seeing a few places in core modules where '#action' is used and validation still works. How is this accomplished? I need a Drupal Jedi to explain this to me, I'm not understanding what I'm doing thats causing validation to fail.
In 5.9:
Comment #8
bigjim CreditAttribution: bigjim commentedI'm having similar issues, I want to POST values to GetActive to add users to an account. Consequently drupal_goto is not an option.
purely by accident, I just noticed the validate functions works if one of the required fields is empty in my form.
sorry posted this in haste, I must have had something else going on, I couldn't reproduce this affect.
Comment #9
gregrenner CreditAttribution: gregrenner commentedYou can use drupal_execute() to POST your form values after validation runs. The process goes something like this:
Feedback?
drupal_execute() http://api.drupal.org/api/function/drupal_execute/5
-Greg
Comment #10
SomebodySysop CreditAttribution: SomebodySysop commentedThanks for digging through to a resolution.
Could you provide an example of this? If you don't have one, then please take a look at the following example, which is my original example modified to follow your logic as I understand it:
I guess the part I'm not understanding is 'your_form_id_here'. If I include the form id, why do I need the #action element which, theoretically, would go to the form whose url is submitted in this element?
In other words, if my hook_menu is:
Then all I really need is
drupal_execute('lesspaper_batch_og_confirm', $form)
and the #action element isn't needed since that's the form it goes to. Correct?Comment #11
bigjim CreditAttribution: bigjim commenteddoes druapl_execute() work for remote addresses, I can't seem to get it to work
here's what I have for validate & submit
Comment #12
greg.harveyBe careful not to create a loop with the drupal_execute stuff. If you need to submit the same form again, you'll need a copy of it, or it will submit over itself forever (or until PHP times out, which could be a looooong time if you're using something like FlashVideo and have it set to 10 minutes...!)
Comment #13
greg.harveyActually, #9 will never work because drupal_execute() ignores '#action' as by design it only executes locally.
You have to use drupal_http_request(). I blogged it here:
http://drupaler.co.uk/blog/validating-submitting-forms-other-websites-dr...
Comment #14
wastrilith2k CreditAttribution: wastrilith2k commentedCan you give an example of how to do this? I'm encountering this issue.
What I am trying to do is have an ubercart product be defined and then when the form is submitted, have it go to another product with the same form values so that any attributes from the first product that are also in the second are automatically populated. But, here is my code using drupal_execute():
If I use the last commented out line, it doesn't loop, but I don't have the form values passed.
Thank you,
James