0

In my controller I am loading a form and including one custom submit handler. However the submit function is not called. I think that it's either not found or not accessible as it is inside the controller class:

class MyController extends ControllerBase {

  //...

  public function myProfile() {
    $user = User::load($this->currentUser->id());
    $form = $this->entityFormBuilder()->getForm($user);

    $form['actions']['submit']['#submit'][] = '::_custom_submit_form';
  }

  protected function _custom_submit_form(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) { 
    $form_state->setRedirect('<front>');
  }

}

If I use hook_form_alter it works, but I don't want to use a hook as I can directly manipulate the form.

2
  • I'd say this submit function needs to be public. public function _custom_submit_form.
    – leymannx
    Jun 26, 2018 at 21:45
  • doesn't work with public
    – Miguel
    Jun 26, 2018 at 22:01

1 Answer 1

5

To understand why your code is not working, you need to understand how the form API works:

  1. The form definition is called
  2. Any form alter hooks are executed, altering the form
  3. The render array is cached
  4. The form is rendered as HTML and sent to the browser
  5. The user submits the form
  6. Drupal checks that the submitted values match the cached form. If values do not match, the values are rejected by Drupal's security system

When you call this code:

$form = $this->entityFormBuilder()->getForm($user);

The caching mentioned in step 3 above has already happened. So when you do this after that line of code:

$form['actions']['submit']['#submit'][] = '::_custom_submit_form';

The submit handler is never called, since the form was cached before this line of code, and therefore your submit handler does not make it into the cache.

To add a submit handler to a form, you need to implement hook_form_alter() (or a variation), which will add the handler before the caching happens. Or, you can extend the form class you are working with, add your own ::submitForm() handler, then call the parent submit from that.

4
  • thank you for the very good and comprehensible explanation. It's a pitty that these kind of things are not documented in this way.
    – Miguel
    Jun 27, 2018 at 8:21
  • so if I don't want the custom submit handler added always to the form but only in one special case, the only possibility is to extend the form class?
    – Miguel
    Jun 27, 2018 at 8:31
  • Or you can use hook_form_alter() and add a logic check.
    – Jaypan
    Jun 27, 2018 at 8:45
  • Thanks @Jaypan!
    – aserww106
    Apr 3, 2019 at 3:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.