-->

Symfony2 Form Component - creating fields without

2020-01-30 12:38发布

问题:

I'm currently trying to use the Symfony2 Form Component though the Silex microframework.

My login form is generated as follows:

$app = $this->app;

$constraint = new Assert\Collection(array(
    'username' => new Assert\NotBlank(),
    'password' => new Assert\NotBlank(),
));

$builder = $app['form.factory']->createBuilder('form', $data, array('validation_constraint' => $constraint));

$form = $builder
    ->add('username', 'text', array('label' => 'Username'))
    ->add('password', 'password', array('label' => 'Password'))
    ->getForm()
;

return $form;

The issue is that the resulting form is being created as follows:

<fieldset>
    <input type="hidden" value="******" name="form[_token]" id="form__token">
    <section class="">
        <label class=" required" for="form_username">Username</label>
        <div><input type="text" value="" name="form[username]" id="form_username" class="text"></div>
    </section>
    <section class="">
        <label class=" required" for="form_password">Password</label>
        <div><input type="password" value="" name="form[password]" id="form_password" class="password"></div>
    </section>
    <section>
        <div><button class="fr submit">Login</button></div>
    </section>
</fieldset>

Whereas I want the name and id attributes to be as follows:

<div><input type="text" value="" name="username" id="username" class="text"></div>
...
<div><input type="password" value="" name="password" id="password" class="password"></div>

I've scoured the web and discovered advice on the 'property_path' option but I believe this is to do with the class used to process the data when used in the actual Symfony2 framework itself.

I've been through the Form Component files and the point as which this is being set is in:

Symfony/Component/Form/Extension/Core/Type/FieldType.php - line 71

public function buildView(FormView $view, FormInterface $form)
{
    $name = $form->getName();

    if ($view->hasParent()) {
        $parentId = $view->getParent()->get('id');
        $parentFullName = $view->getParent()->get('full_name');
        $id = sprintf('%s_%s', $parentId, $name);
        $fullName = sprintf('%s[%s]', $parentFullName, $name);
    } else {
        $id = $name;
        $fullName = $name;
    }
    ...

Unforunately the FormFactory utilises the FormBuilder which then works with the Form class and I've not had enough time to analyse the whole inner workings of the Component.

I do know that fields are added into the 'children' array within the FormBuilder with a corresponding list of options. When the getForm function is called, a new Form is instantiated and each child FieldType is entered into the Form using the add() method. This Form->add() method automatically sets the Form as the parent of each child:

public function add(FormInterface $child)
{
    $this->children[$child->getName()] = $child;

    $child->setParent($this);

    if ($this->dataMapper) {
        $this->dataMapper->mapDataToForm($this->getClientData(), $child);
    }

    return $this;
}

Without starting to override these classes just to remove this does anyone else know of the best method of just displaying the fields name?

It is possible to just pull 'name' instead of 'full_name' in the form_div_layout.html.twig widget_attributes block but I wasn't sure as to whether this was ideal (as the id remains unchanged) or if there was another method or injectable options that would do the trick.

回答1:

Instead of the createBuilder function use:

$builder = $app['form.factory']->createNamedBuilder(null, 'form', $data, array('validation_constraint' => $constraint));

First parameter being the form name.

Example by Bernhard Schussek himself at https://stackoverflow.com/a/13474522/520114



回答2:

In Symfony3, override AbstractType::getBlockPrefix in child class to return null.



回答3:

If you are not using child forms you can set getName method of your form as empty string:

class FormType extend AbstractType {
    // ...

    public function getName() {
        return '';
    }
}