Drupal - Add a custom submission handler to a form

If you use hook_form_node_form_alter() maybe use example code:

function MYMODULE_form_node_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      $form['actions'][$action]['#submit'][] = 'mymodule_form_submit';
    }
  }
}

and for the submit function use:

function MYMODULE_form_submit(array $form, \Drupal\Core\Form\FormStateInterface $form_state){
  //die("I'm not getting run, why :(");
  \Drupal::service('messenger')->addMessage("Why won't this message show?");
}

Creating a custom webform handler plugin for drupal 8.

This document assumes you've already installed and enabled webform and webform-ui

1) Create your webform. - Go to structure -> webforms and press the "+ Add webform" button. - You can either use the ui or use yaml, that's up to you. example yaml for a one field form that takes an email address:

email:
  '#type': email
  '#title': email
  '#title_display': invisible
  '#placeholder': 'ENTER YOUR EMAIL'
  '#attributes':
    class:
      - my-ip

The indentation is important for yaml so make sure you get it right. indents are spaces.

Now save your form.

2) Creating a webform handler plugin

Next we can create a new plugin which will show up in the "Emails/Handlers" section when editing the webform. I will call it myhandler, you can call it what you want, provided you replace all mentions of myhandler with the name you pick.

a) Create a new folder for your plugin, do this in your drupal root (referred to here as /var/www/html/) in the following subfolder: /var/www/html/modules/Custom/myhandler

b) Create a new file in the above directory called myhandler.info.yml in this file goes the following:

name: My Form Handler
description: handles form submits, does something with them. 
package: Custom
type: module
version: 1.0
core: 8.x

3) Create a src directory in your module directory, eg: /var/www/html/modules/Custom/myhandler/src in src create Plugin in Plugin create WebformHandler

(this can be achived in one go using

mkdir -p /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/ 

which will make the entire structure in one go using the -p flag to mkdir.)

4) Create a new file /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/MyFormHandler.php

in that file goes the following php code, i've left the config form setup in so you can see how to configure your plugin if needed.

<?php
namespace Drupal\myhandler\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;


/**
 * Form submission handler.
 *
 * @WebformHandler(
 *   id = "myhandler_form_handler",
 *   label = @Translation("MyHandler form handler"),
 *   category = @Translation("Form Handler"),
 *   description = @Translation("Do something extra with form submissions"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */
class MyFormHandler extends WebformHandlerBase {

     /**
       * {@inheritdoc}
       */

     public function defaultConfiguration() {
        return [
            'submission_url' => 'https://api.example.org/SOME/ENDPOINT',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
        $form['submission_url'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Submission URL to api.example.org'),
            '#description' => $this->t('The URL to post the submission data to.'),
            '#default_value' => $this->configuration['submission_url'],
            '#required' => TRUE,
        ];
        return $form;
    }



  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Your code here.
        // Get an array of the values from the submission.

        $values = $webform_submission->getData();

        // Get the URL to post the data to.
        $post_url = $this->configuration['submission_url'];

        $message = "MyHandler got form data:".print_r($values,1); 
        \Drupal::logger('myformhandler')->error($message);

        return true;
 }
}   
?>

5) Enable your MyHandler module (using drush or extend menu) and then rebuild your drupal cache ( "drush cr" from anywhere under your drupal root (/var/www/html here) would do that if you use drush )

6) edit your webform, go to "Email / Handlers" and click on "+ Add Handler" button You should see your plugin listed, click Add Handler, you should now see a box asking for the submission url. click Save button. If something doesn't look right, or it isn't working, check the apache error log, you might find something helpful there.

7) Test your form - make a submission to the form, and then check the watchdog log (drush ws), you should see the values sent to it. They might be truncated in the output you see, don't panic, it's all there. What you do with this now is up to you.

Hope this helps someone. I cobbled it together from stuff I found around the place and wrote it into a single document. Thanks to the others who got me here.


if using hook_form_BASE_FORM_ID_alter in Drupal 8 core 8.4.3, I found the ways of adding the custom submit handler didn't work. This worked for adding the submit handler function name:

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

In another situation, using hook_form_FORM_ID_alter in Drupal 8.4.5, I found the above did not work for adding the custom submit handler. Instead, this worked:

$form['actions']['submit']['#submit'][]  = 'mymodule_submit_handler';

Tags:

Forms

8