I'm trying to understand how to port the following D7 code.


function x_menu() {
    $menu['x/form/test/%/%'] = [
        'page callback' => 'drupal_get_form',
        'page arguments' => ['x_form_test', 3, 4],
        'type' => MENU_CALLBACK,
        'title' => 'Test Form',
    ];
    return $menu;
}


function x_form_test(&$form, $form_state, $arg1, $arg2) {
    return $form;
}

From what I can glean from the documentation of the Routing and Form API, the new way to connect a path to a form is to put this in x.routing.yml:

x.form_test:
    path: 'x/form/{arg1}/{arg2}',
    defaults:
        _form: '\Drupal\x\XFormTest'
        _title: 'Test Form'

and then create a form class XFormTest that ultimately descends from FormBase.

However, it's clearly impossible to add extra arguments to inherited functions like public FormInterface::buildForm(array $form, FormStateInterface $form_state).
See comment below.
How can I read $arg1 and $arg2 in buildForm, preferably while still pointing the route at the form rather than putting a Controller around it?

https://www.drupal.org/node/2092643

Comments

slewazimuth’s picture

Maybe its just me, but I got the impression from the documentation on Drupal 8 that the system functions on a request/response basis. Therefore, information in a request is ALWAYS available. So if I wanted the information for 'arg1' and didn't have more specific information handy, I would just use \Drupal::request()->get('arg1') to get the arg1 value.

That should make argument information available no matter where you are. You can also setup default values for arguments in the routing file.

x.form_test:
    path: 'x/form/{arg1}/{arg2}',
    defaults:
        _form:  '\Drupal\x\XFormTest'
        _title:  'Test Form'
        arg1:  'default value1'
        arg2:  'default value2'

I'm sure there is likely more specific information available but I'm only looking at things from a very rudimentary level.

cburschka’s picture

I misinterpreted the error I was getting when I tried to override the buildForm() function. When it failed with an "incompatible arguments" error, I assumed that PHP inheritance was similarly restricted as Java (which does require exact signature matches).

PHP, which has optional function arguments (instead of overloading), allows adding such arguments to the overriding function as they do not alter the "contract", but merely extend it transparently. There's nothing wrong with directly transferring the D7 form builder arguments ($form, $form_state, $arg1 = '...') into the D8 arguments (array $form, FormStateInterface $form_state, $arg1 = '...').

The "incompatible" error I got was actually due to accidentally copying the submitForm() signature and turning $form into &$form. Switching an argument to by-reference does alter the contract, so it's not allowed.