Profile picture for user admin
Daniel Sipos
10 Feb 2014

In this article we are going to look at a cool Webform api function that allows us to interfere with the submissions being saved to the database. Interfere sounds like a negative thing but because the Webform module is so awesome, we can perform all sorts of operations on the submitted data before saving it.

Among the many API functions the Webform module comes with, a cool one is hook_webform_submission_presave() and that's what we will look at in this article. This function gets called whenever a user submits a form but before the submission gets saved. And we have available as parameters the $node object and the $submission object that contains the data and that can be altered (passed by reference).

Use case

Why would you need it? To illustrate how you can use it, I am going to show you what I needed, followed by how I implemented it with hook_webform_submission_presave().

My user accounts had some fields on it (first and last name) and all users on the site were invited to submit once a particular webform. And since I already have their first and last names in the $user object, I wasn't going to ask them to provide them again in the webform. And yes, I needed the webform submission to contain the names.

Implementation

The first thing I did was create 2 hidden fields on the webform for the first and last names. Users filling in the info wouldn't even realize they are there. Next, I implemented the hook:

/**
 * Implements hook_webform_submission_presave().
 */
function my_module_webform_submission_presave($node, &$submission) {
  // Get the submission user object.
  $user = user_load($submission->uid);

  // Check if $user does have the first name filled.
  if (!empty($user->field_first_name)) {
    $first_name = $user->field_first_name['und'][0]['value'];
    // Add the $user first name to the submission data.
    $submission->data[4]['value'][0] = $first_name;
  }

  // Same as above but for the last name.
  if (!empty($user->field_last_name)) {
    $last_name = $user->field_last_name['und'][0]['value'];
    $submission->data[5]['value'][0] = $last_name;
  }

}

As you can see from my comments, the first thing I do is retrieve the $user object of the submission author. Next, I check if the relevant fields are set (to make sure no errors are thrown if there is a user without any names), and assign them to the data array in the $submission object. However, as you can see, I hardcoded the webform component id when doing this assignment:

$submission->data[4]['value'][0] = $first_name;
$submission->data[5]['value'][0] = $last_name;

This means I looked them up before and am sure they will not change (i.e. get deleted and/or recreated). It's probably not the bestest of solutions but if you are certain of the webform you created, you can do it like this. Another approach would be to iterate through all the components in the data array and check for the machine name of the field and do the assignment based on that. So you have plenty of options.

Please keep in mind that in newer versions of Webform it's like this:

$submission->data[4][0] = $first_name;
$submission->data[5][0] = $last_name;

Additionally, you'll notice that I do not use the $node object at all which means that this hook will do its job on all webforms. This is because I only have one webform on the site (and I'm certain I'll only have one). But that's why the $node object is there, so you can check against and condition your logic to certain nodes that meet various criteria. The choices are many.

Conclusion

In this article we've looked at using this awesome hook provided by the Webform module: hook_webform_submission_presave(). You can do a lot of stuff with it. We've seen only how to add aditional information to the submission but you can also alter the passing submission values. So keep in mind there's this nifty function you can use when you're building your webforms.

Profile picture for user admin

Daniel Sipos

CEO @ Web Omelette

Danny founded WEBOMELETTE in 2012 as a passion project, mostly writing about Drupal problems he faced day to day, as well as about new technologies and things that he thought other developers would find useful. Now he now manages a team of developers and designers, delivering quality products that make businesses successful.

Contact us

Comments

Sonjoy 30 Jun 2014 08:09

Webform submission information

Useful information on Webform submission and it Implementation shared .. :)

johndubo 20 Feb 2015 00:15

File directory

Could you use this hook to set the upload file directory based on submission info (in my case, a select option)? Thanks for this site. It is super useful!

johndubo 20 Feb 2015 23:18

In reply to by johndubo (not verified)

It looks like the file

It looks like the file directory is part of the $node object. Is info within that object changeable with this hook since it is not passing as a reference?

Daniel Sipos 24 Feb 2015 17:21

In reply to by johndubo (not verified)

Hey there,

Hey there,

The $node object is not passed by reference so it cannot be altered. Nor you should in this case. It is passed only as way to determine context for the submission.

johndubo 24 Feb 2015 17:25

In reply to by admin

Right, I ended up using

Right, I ended up using multiple upload fields (with different directories) to correspond to which option was chosen from the select box. Kinda clunky way to do it, but it works. Thanks!

Abe 27 Oct 2015 06:03

Slight change required with more recent release of webforms

$submission->data[5]['value'][0] = $last_name;

need to remove ['value'] for this solution to keep working!

Trush 15 Apr 2016 16:39

need sid

i want submission id from the submitted form to store in my custom table how can i achieve this?
Can u help me in this?
Thanks in advance.

NuclearWessel 20 Jul 2016 18:16

In reply to by Trush (not verified)

Getting the SID

hook_webform_submission_presave, as it's name implies, runs before the form is saved and before it gets a SID. What you need is hook_webform_submission_insert, which is called after the form has been saved and will include the SID in $submission->sid. Good luck!

Fab 31 Jan 2017 13:00

If you want to use field

If you want to use field machine name instead of cid of the field you can use

 function _tools_webform_get_components($node) {
  $cmps = array();
  if (!empty($node->webform)) {
    foreach ($node->webform['components'] as $cmp) {
      $cmps[$cmp['form_key']] = $cmp['cid'];
    }
  }
  return $cmps;
}: 

and then use :

$cmps = _tools_webform_get_components($node);
and use : $submission->data[$cmps['your_field_machine_name']][0]
Arito Melo 17 Jul 2017 15:33

Quick fix in how to set the variabel!

$cmps = _tools_webform_get_components($node);
and use : $submission->data[$cmps['your_field_machine_name']]['value'][0] = 'new_value';

Martin 23 Jun 2023 12:31

helpful for Backdrop CMS webform

As is so often the case with Backdrop CMS, if someone hasn't written about it yet, we can find a Drupal 7 way of doing it and often just works or works with small modifications.
This was really helpful for my custom module, and the suggestion from 'Fab' is the icing on the cake to make it easier to configure.
Thanks

Gowtham 25 Sep 2024 14:27

Prevent submission if a condition is true

I am using hook_webform_submission_presave() in my code and I want to show an error message and prevent submission. when I try $webform_submission->addError($key, t('custom error message')); it's throwing error that the method is not defined. Can anyone help me with this.

Add new comment