How is $form['#action'] encoded? I have the following set up:


Webform "my_webform" 
Entity type "activity"
The "activity" entity type includes a webform reference field
Activity ID 14 has some content and a reference to "my_webform"
Activity ID 14 has the path "/activity/14"


In a custom module I have a hook_form_alter() to perform some changes based on certain conditions. I'm using the devel module and kint() to debug the structure.

function MODULE_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
  if ($form_id === 'my_form) {
    kint($form['#action']);
  }
}


Here's the first bit of strangeness:



kint() states the length of the string as being 55 characters. To work out what the characters are, I used the following:

function MODULE_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
  if ($form_id === 'my_webform) {
    $array = [];
    for ($i=0; $i&lt;strlen($form['#action']); $i++) {
      $array[$i] = $form['#action'][$i];
    }
    kint($array);
    print implode(' ',$array);
  }
}


This produced the following:

f o r m _ a c t i o n _ p _ p v d e G s V G 5 z N F _ X L G P T v Y S K C f 4 3 t 8 q Z Y S w c f Z l 2 u z M

To get a proper look, I tried to remove this spaces:

print str_replace(" ", "", 'f o r m _ a c t i o n _ p _ p v d e G s V G 5 z N F _ X L G P T v Y S K C f 4 3 t 8 q Z Y S w c f Z l 2 u z M');


The result:  /activity/14

The full hook_form_alter():

function MODULE_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
  if ($form_id === 'my_webform) {
    $array = [];
    for ($i=0; $i&lt;strlen($form['#action']); $i++) {
      $array[$i] = $form['#action'][$i];
    }
    kint($array);
    print implode(' ',$array);
    print str_replace(" ", "", 'f o r m _ a c t i o n _ p _ p v d e G s V G 5 z N F _ X L G P T v Y S K C f 4 3 t 8 q Z Y S w c f Z l 2 u z M');

    // exit;
  }
}


Uncommenting the exit; results in the full 55 character string so something's happening after this hook_form_alter() is invoked. Where and how this is happening? How does it alter what print displays after the fact?

I've hardcoded the string in str_replace() for testing but this can be replaced with print implode('',$array);
The form action url is placeholdered to make the form cacheable when used on different pages:

Drupal\Core\Form\FormBuilder::prepareForm

  public function prepareForm($form_id, &amp;$form, FormStateInterface &amp;$form_state) {
    $user = $this-&gt;currentUser();

    $form['#type'] = 'form';

    // Only update the action if it is not already set.
    if (!isset($form['#action'])) {
      // Instead of setting an actual action URL, we set the placeholder, which
      // will be replaced at the very last moment. This ensures forms with
      // dynamically generated action URLs don't have poor cacheability.
      // Use the proper API to generate the placeholder, when we have one. See
      // https://www.drupal.org/node/2562341. The placeholder uses a fixed string
      // that is Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
      $placeholder = 'form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM';

      $form['#attached']['placeholders'][$placeholder] = [
        '#lazy_builder' =&gt; ['form_builder:renderPlaceholderFormAction', []],
      ];
      $form['#action'] = $placeholder;
    }


The placeholder is replaced before the cached page is delivered to the client. See FormBuilder::renderPlaceholderFormAction and FormBuilder::buildFormAction

The confusion in your debugging attempts is caused by placeholders being replaced not only in rendered forms, but also in debug output you put on the page via kint() or print.