Symfony 2搜索表单呈现不需要的搜索字段。我可以禁用此行为吗?

时间:2015-02-27 09:38:56

标签: php forms symfony search render

修改:此问题涉及 Symfony 2.7 Symfony 2.8 + 请参阅下面的Ogi答案。

我的require中的composer.json部分如下所示:

"require": {
    "php": ">=5.3.3",
    "symfony/symfony": "2.3.*",
    "doctrine/orm": "~2.2,>=2.2.3,<2.5",
    "doctrine/dbal": "<2.5",
    "doctrine/doctrine-bundle": "~1.2",
    "twig/extensions": "1.0.*",
    "symfony/assetic-bundle": "~2.3",
    "symfony/swiftmailer-bundle": "~2.3",
    "symfony/monolog-bundle": "~2.4",
    "sensio/distribution-bundle": "~2.3",
    "sensio/framework-extra-bundle": "~3.0,>=3.0.2",
    "sensio/generator-bundle": "~2.3",
    "incenteev/composer-parameter-handler": "~2.0",

    "braincrafted/bootstrap-bundle": "~2.0",
    "twbs/bootstrap": "3.2.*",
    "jquery/jquery": "1.11.*",
    "stof/doctrine-extensions-bundle": "~1.1@dev"
},

注意:最后四个软件包是在Symfony2标准版之上添加的。

Symfony 2 Forms文档章节之后,我尝试创建搜索表单。所以,我创建了一个实体类:

<?php
namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class SearchQuery
{
/**
 * @Assert\NotBlank()
     * @Assert\Type(type="string", message="form.search.query.validation.type")
     * @Assert\Length(
     *      min = 3,
     *      max = 50,
     *      minMessage = "form.search.query.validation.min",
     *      maxMessage = "form.search.query.validation.max"
     * )
     */
    protected $query;

    public function __construct($query = '')
    {
        $this->setQuery($query);
    }

    public function getQuery()
    {
        return $this->query;
    }

    public function setQuery($query)
    {
        $this->query = $query;
    }
}

表单类型:

<?php
namespace AppBundle\Form\Type;

use 
    Symfony\Component\OptionsResolver\OptionsResolverInterface,    
    Symfony\Component\Form\AbstractType,
    Symfony\Component\Form\FormBuilderInterface
;

class SearchType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('query', 'text', array(
                'label' => '',
                'attr' => array(

                ),
            ))
            ->add('save', 'submit', array(
                'label' => '',
            ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\SearchQuery',
            'attr' => array(
                'id' => 'search-form'
            )
        ));
    }

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

渲染输出:

<form name="search" method="post" action="/app_dev.php/search" id="search-form" role="form">

    <input type="search" id="search" name="search" required="required" class="form-control" value="">

    <div class="form-group">
        <label class="control-label required" for="search_query">Query</label>
        <input type="text" id="search_query" name="search[query]" required="required" class="form-control">
    </div>
    <div class="form-group">
        <button type="submit" id="search_save" name="search[save]" class="btn btn-primary">Save</button>
    </div>
    <input type="hidden" id="search__token" name="search[_token]" class="form-control" value="5f0e9c4a9d4e251fc62e25686cf810eaa0ff4331">
</form>

问题是Symfony 2 Forms,BraincraftedBootstrapBundle和Twig之间的某些东西试图发挥智能并添加这个不需要的字段:

<input type="search" id="search" name="search" required="required" class="form-control" value="">

我注意到只有SearchType::getName()方法返回'search'时才会发生这种情况。如果我将其更改为:

class SearchType extends AbstractType
{

    [...]

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

    [...]

}    

一切都按预期工作,渲染输出为:

<form name="search_foo" method="post" action="/app_dev.php/cautare" id="search-form" role="form">
    <div id="search_foo">
        <div class="form-group">
            <label class="control-label required" for="search_foo_query">Query</label>
            <input type="text" id="search_foo_query" name="search_foo[query]" required="required" class="form-control">
        </div>
        <div class="form-group">
            <button type="submit" id="search_foo_save" name="search_foo[save]" class="btn btn-primary">Save</button>
        </div>
        <input type="hidden" id="search_foo__token" name="search_foo[_token]" class="form-control" value="68ee88cb3adef211b993806029ba3fa989322c80">
    </div>
</form>

当然,我可以将名称更改为其他内容并继续前进,但它就像是在我脑海中敲打钉子而不了解窗帘背后真正发生的事情。

我甚至试图将field type设置为search而不是text,希望如果它看到有搜索字段会让我一个人赢得&#39 ; t尝试猜测我的意图是什么,但不是,它仍会打印出不需要的字段。

1 个答案:

答案 0 :(得分:1)

您可能已经看到@aistis在其评论中创建的问题。

我从您的composer.json文件中看到您似乎使用了symfony 2.3。所以这个错误很奇怪,因为它应该只发生在2.8 ......

之后

无论如何,解决方案非常简单,但并不明显:您应该在表单类型中实现getBlockPrefix方法:

<?php
namespace AppBundle\Form\Type;

// [...]

class SearchType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // [...]
    }

    public function getBlockPrefix()
    {
        return 'app_search'
    }
}

保持简短:这可以通过Symfony Form组件的最新更改来解释,删除表单别名和getName()方法。
表单类型现在由其完全限定类名称标识 当一个表单被渲染时,它将从FQCN计算表单名称,只保留小写的&amp;蛇类名称减去Type。然后它将使用此计算名称来呈现与此名称匹配的表单主题块。

然而,作为一个缺点,命名与现有表单类型相同的表单类型将导致您遇到的意外行为 好消息是,您可以通过覆盖表单类型中的getBlockPrefix方法来覆盖表单主题名称的计算方式。因此,上面的解决方案。

PS:如果你真的使用Symfony 2.8+,你应该摆脱2.7中弃用的setDefaultOptions方法,而不是新的configureOptionshttps://github.com/symfony/symfony/blob/2.8/UPGRADE-2.7.md#form

另请参阅2.8中的Symfony Form组件的弃用和升级路径列表:https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#form