Last updated 9 December 2016. Created on 31 May 2012.
Edited by jrockowitz, rudiedirkx, jenlampton, ashish_nirmohi. Log in to edit this page.

This page documents changes between the Webform 3.x version and the Webform 4.x version, including any information you need to know when upgrading from one version to the next.

The most important thing to keep in mind when upgrading from Webform 3.x to 4.x is that you cannot downgrade after update.php has been run, unless you restore a database backup created before the update.php run. Webform 4.x makes several database changes and downgrading after you have upgraded is not possible. Be sure to test your upgrade on a development server or localhost copy before upgrading your production server.

Changes between Webform 3.x and 4.x:








Detailed Change Instructions


Token System Replaced with D7-style Tokens

(issue) Webform previously used its own custom token system to provide common tokens such as %title, %username, or %value[key]. In Webform 4.x, we use the token system provided by Drupal 7 core, which uses a format such as [node:title], [current-user:name], or [submission:values:key].

Most tokens will be upgraded for you, however some tokens do not have equivalents and no longer work. These include %post, %request, %cookie, and %session. The %get token (which maps to PHP's $_GET variable) has the equivalent token [current-page:query:key].

As mentioned, most tokens are upgraded for you in any configuration, default values, e-mail templates, etc. However tokens that are hard-coded within things such as node exports or webform-mail.tpl.php files will need to be changed manually. The complete map of replacements is as follows:

%username               [current-user:name]
%useremail              [current-user:mail]
%uid                    [current-user:uid]
%date                   [submission:date:long]
%ip_address             [current-user:ip-address]
%site                   [site:name]
%nid                    [node:nid]
%title                  [node:title]
%email_values           [submission:values]
%submission_url         [submission:url]
%sid                    [submission:sid]
%server[REQUEST_URI]    [current-page:url]
%get[$key]              [current-page:query:$key]
%email[$key]            [submission:values:$key]
%value[$key]            [submission:values:$key:nolabel]
%safe_key[$key]         [submission:values:$key:key]
%profile[$key]          [current-user:$key]


The $submission->data and $form_state['values'] variable structure changed

(issue) In Webform 3.x, values within the Webform $submission variable as retrieved by webform_get_submission() had a structure like the following:

Webform 3.x:

$submission->data[$cid]['value'][0] = 'string value';

However in 4.x, the superflous "value" key was eliminated to increase consistency in Webform's internal data structures during form processing.

Webform 4.x:

$submission->data[$cid][0] = 'string value';

Additionally, in Webform 3.x, the $form_state['values'] array was split in two pieces, $form_state['values']['submitted'] and $form_state['values']['submitted_tree']. In Webform 4.x, the $form_state['values']['submitted_tree'] array no longer exists, and the $form_state['values']['submitted'] array is now identical to the structure of a fully loaded $submission array, making the two structures more easily interchangeable.

Same-page conditionals built into main module require "Webform Conditional" module be uninstalled

(issue) Before upgrading to Webform 4.x, if you have installed the "Webform Conditional" module you MUST disable and then uninstall the module using the Drupal uninstaller (admin/module/uninstall).


The $component['mandatory'] property has been renamed to $component['required']

(issue) Webform 4.x has switched from using the legacy terminology "mandatory" to "required" everywhere in its code. This includes in all components ($component['required']) and in the database table webform_component.

Webform 3.x:

$element['#required'] = $component['mandatory'];

Webform 4.x:

$element['#required'] = $component['required'];

The theme_webform_components_form() has its variables preprocessed

(issue) The theme_webform_components_form() used to contain a large amount of logic code. This logic has all been moved to a preprocess function: template_preprocess_webform_components_form(). If you have overridden the theme_webform_components_form() theme function on your site, you will need to remake your overridden version.

Webform 3.x:
See theme_webform_components_form() on

Webform 4.x:
See preprocess_webform_components_form() on
See theme_webform_components_form() on


Webform exporter classes now use PHP5-syntax for constructors

(issue) Constructors have changed in exporter classes (such as the webform_exporter_excel and webform_exporter classes) to use __construct() instead of functions that match the class name. If you provide a custom exporter for Webform, it will need to be updated to use the PHP5 syntax:

Webform 3.x:

class webform_exporter_excel extends webform_exporter_delimited {
  function webform_exporter_excel($options) {
    $options['delimiter'] = '\t';

Webform 4.x:

class webform_exporter_excel extends webform_exporter_delimited {
  function __construct($options) {
    $options['delimiter'] = '\t';

Webform legacy-Excel class renamed and disabled by default

(issue) The class webform_exporter_excel has been renamed to webform_exporter_excel_delimited. This was done to distinguish the old TSV-based Excel exports from the new native-Excel exporter (which is in the webform_exporter_excel_xlsx class).

In addition, the new native Excel exporter is the only exporter available in the UI by default. If you need to enable the old Excel exporter, you may do so by setting this hidden variable in your settings.php file:

$conf['webform_excel_legacy_exporter'] = TRUE;

Webform security functions renamed: _webform_filter_xss(), _webform_filter_descriptions(), and _webform_filter_values()

(issue) The Webform security functions have been overhauled to solve several problems: They're now in the public namespace, since 3rd party modules regularly use these functions. The token replacement has been separated from security checking.

In general, you can flip your functions in the following way:

_webform_filter_xss() => webform_filter_xss()
_webform_filter_descriptions() => webform_filter_descriptions()
_webform_filter_values() => webform_replace_tokens()

Note that in 3.x, the last ($strict) parameter for _webform_filter_values() was TRUE by default, meaning it assumed it was being output to HTML and would run check_plain() on the output. In 4.x, the last parameter ($sanitize) is FALSE by default and will not be safe for outputting directly to HTML.

This example is a slimmed down version of a _webform_render_[component]() function that demonstrates all of these changes:

Webform 3.x:

  $element = array(
    '#type' => 'textfield',
    '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
    '#default_value' => $filter ? _webform_filter_values($component['value'], $node, NULL, NULL, TRUE) : $component['value'],
    '#description' => $filter ? _webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],

Webform 4.x:

  $element = array(
    '#type' => 'textfield',
    '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'],
    '#default_value' => $filter ? webform_replace_tokens($component['value'], $node) : $component['value'],
    '#description' => $filter ? webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],

Webform-enabled content types are now controlled by separate variables instead of the single "webform_enabled_types" variable

(issue) In order to make Webform-enabled content types more easily exportable and discoverable, the single variable "webform_enabled_types" variable has been split into separate variables with the name "webform_node_" . $node_type.

Webform 3.x

if (in_array($node->type, webform_variable_get('webform_node_types'))) {
  // Do something.

Webform 4.x

if (variable_get('webform_node_' . $node->type, FALSE)) {
  // Do something.
// OR:
if (in_array($node->type, webform_node_types())) {
  // Do something.

The first approach is recommended for performance reasons, but the latter should be used if looping through all content types that are Webform-enabled.

Classes are used instead of IDs whenever possible in Webform's output

(issue) In order to make Webform's conditional logic work when the same form is rendered multiple times on the same page and to increase consistency for themers, Webform 4.x reduces the use of HTML "id" attributes in preference of "class" attributes whenever possible.

For example a component with the form key "my_component_key" would be changed as follows:

Webform 3.x

<div class="..." id="webform-component-my-component-key">
  <label ...>Field label </label>
  <input ...>
  <div class="description">Description goes here.</div>

Webform 4.x

<div class="... webform-component--my-component-key">
  <label ...>Field label </label>
  <input ...>
  <div class="description">Description goes here.</div>

Note that the new class name has two dashes separating "webform-component" and the form key, this is to avoid conflicts with classes such as "webform-component-textfield" or "webform-component-inline". Any CSS that targeted elements using the HTML "id" attribute will need to be updated to use the new classes instead of the IDs.


Number of arguments for hook_webform_select_options_info() 's callback function changed

(issue)(issue) As part of adding node tokens to select component option labels the filter argument was removed from the callback call for hook_webform_select_options_info() .

For example webform_options_days changed as follows:

Webform 3.x

webform_options_days($component, $flat, $filter, $arguments)

Webform 4.x

webform_options_days($component, $flat, $arguments)

webform.api.php is already updated accordingly.


theme_webform_element() needs to be rethemed due to new preprocess function

(issue) In order to reduce code in the theme_webform_element() function and to make it so that modules can alter the list of wrapper classes, the theme_webform_element() function was split up to use a preprprocess function to assign classes and do other logic before the theme function is run. If you have themed Webform form elements in your theme's template.php file, it is recommended to copy/paste the original theme_webform_element() and retheme the output. If this is not done, classes may be output twice on the front-end. This usually does not cause any visual problems, but it does result in redundant output.

Looking for support? Visit the forums, or join #drupal-support in IRC.


RyanJ_DMC12’s picture

What is the procedure for upgrading from 3.x to 4.x? I know you need to do a database back up first but are there specific Drush commands to do the upgrade? Can I just do drush dl webform-7.x-4.x ? Do I need to disable and remove the 3.x module completely and then install the 4.x version? I just want to make sure I'm doing it right the first time since you can't downgrade without having to reload the previous database instance.

Pimmy’s picture

Agree - The online docs should be improved by adding how to perform the update - information which you can find in the README:
Firstly, most of the users are using the GUI to perform module installations or upgrades - in this use case the user does not extract the package, hence he/she would not find the instructions.
Secondly, the instructions are in the README - while they should be in the UPGRADE or INSTALL file.

Anyway, it is as simple as that:

1. Copy the entire webform directory the Drupal sites/all/modules directory.

2. Login as an administrator. Enable the module in the "Administer" -> "Modules"

3. (Optional) Edit the settings under "Administer" -> "Configuration" ->
"Content authoring" -> "Webform settings"

4. Create a webform node at node/add/webform.

Upgrading from previous versions
Note that you must be running the latest 3.x version of Webform (for either
Drupal 6 or Drupal 7) before upgrading to Webform 4.x.

If you have contributed modules, custom modules, or theming on your Webforms,
please read over the documentation for upgrading your code for Webform 4.x at

1. MAKE A DATABASE BACKUP. Upgrading to Webform 4.x makes a signficant number of
database changes. If you encounter an error and need to downgrade, you must
restore the previous database. You can make a database backup with your
hosting provider, using the Backup and Migrate module, or from the command

2. Copy the entire webform directory the Drupal modules directory, replacing the
old copy of Webform. DO NOT KEEP THE OLD COPY in the same directory or
anywhere Drupal could possibily find it. Delete it from the server.

3. Login as an administrative user or change the $update_free_access in
update.php to TRUE.

4. Run update.php (at

mario.awad’s picture

This is how you do the upgrade from Webform 3.x to 4.x with Drush.

First, make sure you change the below to the latest version of webform. As of today it's webform-7.x-4.10.

drush dl ctools
drush dl views
drush en ctools -y
drush en views -y
drush dl webform-7.x-4.10 -y
drush updatedb -y

This downloads ctools then views which are now required by webform 4.x. Then you enable both. Note here that I'm downloading and enabling safely cause from the first two commands if the modules are already downloaded Drush will tell you and then no need to download them again. Then you specify to Drush you want that specific version of the webform module (otherwise you'd stay on the 3.x branch) and override the older files of webform (properly, i.e., without keeping previous 3.x files) and finally you run updatedb which is similar to running update.php from the web interface.


phponwebsites’s picture

Now i have used webform 7.x-4.2. i want to upgrate to webform 7.x-4.5.
How to upgrade this?

drurian’s picture

In Webform 3 I used keys in submitted tree to get the values. What's the best way to do it now? - Drupal Video Tutorials

SiaoKiax3’s picture

The title is about upgrading from 7.3 to 7.4.
But the content is about changes from 7.3 to 7.4.

It's confusing for user when they looking for steps to upgrade from 7.3 to 7.4.
Please create new page for the changes and update the correct info regarding the updating steps.

rajibmp’s picture

If you have Drush installed then you can update to webform 4 easily with Drush commands

To update to latest dev version
drush up webform-4.x

To update to specific version (in this case stable at the time of writing)
drush up webform-4.12

The results will be like:

Name Installed Version Proposed version Message
Webform (webform) 7.x-3.24 7.x-4.12 Specified version available

Update information last refreshed: Thu, 03/31/2016 - 13:12
Code updates will be made to the following projects: Webform [webform-7.x-4.12]

Note: A backup of your project will be stored to backups directory if it is not managed by a supported version control system.
Note: If you have made any modifications to any file that belongs to one of these projects, you will have to migrate those modifications after updating.
Do you really want to continue with the update process? (y/n): y
Project webform was updated successfully. Installed version is now 7.x-4.12.
Backups were saved into the directory /home/rajib//drush-backups/sitename/20160331101620/modules/webform.[ok]
Webform 7401 Rewrite token replacement system to use D7 tokens. If needed, please download and install the Token module from Otherwise some tokens will not be rendered.
Webform 7402 Add the webform_conditional database table.
Webform 7403 Convert per-component conditionals to new more flexible conditional system.
Webform 7404 Remove files left over from deleted submissions. Such files are now deleted automatically.
Webform 7405 Add an "extra" column to the e-mail table for for non-queryable options.
Webform 7406 Convert the "webform_use_cookies" setting to "webform_tracking_mode".
Webform 7407 Remove orphaned conditional rules.
Webform 7408 Rename the "mandatory" column to "required".
Webform 7409 Add progress bar columns to the webform table.
Webform 7410 Remove the "teaser" column from the "webform" table.
Webform 7411 Remove [submission:values:x] token use of :nolabel and add :withlabel.
Webform 7412 Split webform_node_types as content type specific.
Webform 7413 Add preview page columns to the webform table.
Webform 7414 Change email subject, from_name and from_address fields to type 'TEXT'.
Webform 7415 Increase length of webform.redirect_url.
Webform 7416 Add columns for serial numbered submissions. Add serial numbers to existing submissions.
Webform 7417 Change to text to allow for longer labels.
Webform 7418 Upgrade the "extra" column in the e-mail table to be consistent with a new webform installation. In version
7.x-4.0-rc6 and earlier, the extra field was added with 'not null' FALSE, cause the schema module to report in
mismatch. While functionally this causes no problem, this update removes the schema module's warning.
Webform 7419 Add an index on submitted data.
Webform 7420 Extend access to the WEBFORM tab to anyone who can access the node's EDIT tab.
Webform 7421 Set the administrator option for an HTML-capable mail system to the current automatically-detected option.
Webform 7422 Remove the administrator option "Include webform forms in search index" and rely on the Search Index view mode
Webform 7423 Convert conditionals to be able to support multiple actions per conditional. Backup your database before
proceeding. WARNING: Sites with many, many conditionals should execute this update via drush to avoid a PHP
Webform 7424 Convert conditional actions of "hide" to "isn't shown".
Webform 7425 Add "exclude empty" option to emails.
Webform 7426 Add configuration to continue sending individual e-mails to multiple recipients.
Webform 7427 Add database columns for submission completed and modified timestamps. Sites with many submissions may wish to use
drush to execute this update.
Webform 7428 Add a "confidential" option to webforms.
Webform 7429 Add a column to the submission table to store the page on which to resume a draft. Sites with many, many
submissions may wish to execute this update with 'drush updatedb'.
Webform 7430 Add a column to the emails table to allow disabling.
Do you wish to run all pending updates? (y/n): y
Performed update: webform_update_7401 [ok]
Performed update: webform_update_7402 [ok]
Performed update: webform_update_7403 [ok]
Performed update: webform_update_7404 [ok]
Performed update: webform_update_7405 [ok]
Performed update: webform_update_7406 [ok]
Performed update: webform_update_7407 [ok]
Performed update: webform_update_7408 [ok]
Performed update: webform_update_7409 [ok]
Performed update: webform_update_7410 [ok]
Performed update: webform_update_7411 [ok]
Performed update: webform_update_7412 [ok]
Performed update: webform_update_7413 [ok]
Performed update: webform_update_7414 [ok]
Performed update: webform_update_7415 [ok]
Performed update: webform_update_7416 [ok]
Performed update: webform_update_7417 [ok]
Performed update: webform_update_7418 [ok]
Performed update: webform_update_7419 [ok]
Performed update: webform_update_7420 [ok]
Performed update: webform_update_7421 [ok]
Performed update: webform_update_7422 [ok]
Performed update: webform_update_7423 [ok]
Performed update: webform_update_7424 [ok]
Performed update: webform_update_7425 [ok]
Performed update: webform_update_7426 [ok]
Performed update: webform_update_7427 [ok]
Performed update: webform_update_7428 [ok]
Performed update: webform_update_7429 [ok]
Performed update: webform_update_7430 [ok]
'all' cache was cleared. [success]
Finished performing updates. [ok]

jaesperanza’s picture

I have existing webforms created on version 3. What happens to these after version 4 upgrade? How do I migrate these? Sorry if I am missing anything from the documentation I can't seem to find any on info on this concern. Thanks, mates!

rajibmp’s picture

I think you should try upgrading it to 4.x in test servers and verify everything works as expected before updating anything in production directly.

In my case, the migration using the above Drush command went smoothly and all the webforms built in 3.x are well migrated in 4.x without losing any functionality and saved results.

The migration was smooth as mango smoothie and works just like before without any issues.

jaesperanza’s picture

Yes, I did test actually locally and on test server, but seems the webforms created before on ver 3 have gone missing. Switching themes did not fix it, ruling out theme display issues. I will test and troubleshoot some more. Good to know though it works, one reason and validation to work on my issues further. Thanks, raj!