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

Posted

技术标签:

【中文标题】Symfony 2 搜索表单呈现一个不需要的搜索字段。我可以禁用此行为吗?【英文标题】:Symfony 2 search form renders an unwanted search field. Can I disable this behaviour? 【发布时间】:2015-04-29 23:18:52 【问题描述】:

编辑:这个问题指的是 Symfony 2.7,对于 Symfony 2.8+,请参阅下面 Ogi 的回答。

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

"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 docs 一章,我正在尝试创建一个搜索表单。所以,我创建了一个实体类:

<?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 希望如果它看到有一个搜索字段会让我一个人呆着,不会试图猜测我的意图是什么,但不,它仍然会打印不需要的字段。

【问题讨论】:

我在 Symfony 2.8 和 3.0 上遇到了同样的问题。很奇怪的行为。或许社区里有人会有时间去挖掘它github.com/symfony/symfony/issues/16899 【参考方案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 表单组件的最新变化来解释,去掉表单别名和 getName() 方法。 表单类型现在由其完全限定类名标识。 呈现表单时,它将从 FQCN 计算表单名称,仅保留小写和蛇形类名称减去 Type。然后它会使用这个计算出来的名字来渲染匹配这个名字的表单主题块。

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

P.S:如果你真的在使用 Symfony 2.8+,你应该摆脱 2.7 中不推荐使用的 setDefaultOptions 方法,转而使用新的 configureOptions 一个:https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.7.md#form

还可以在此处查看 2.8 中 Symfony 表单组件的弃用和升级路径列表:https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#form

【讨论】:

感谢您提供书面答复!我的问题是 1 年,在 Symfony 2.8 发布之前。我不知道这是如何在 2.8+ 中实现的,但是我现在正在开发一个 2.7 的项目,我无法摆脱 getName() 方法,因为它存在于 FormTypeInterface 中,由 AbstractType 实现.此外,没有getBlockPrefix() 方法。抱歉,我无法将您的答案标记为已接受,尽管它的存在对那些正在寻找 2.8+ 的人来说是件好事。

以上是关于Symfony 2 搜索表单呈现一个不需要的搜索字段。我可以禁用此行为吗?的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 - 使用没有附加任何实体的表单生成器

Symfony 5 Typeahead 搜索 [关闭]

使用会话值设置表单数据而不提交此 symfony 表单

警告:非法字符串偏移量'city'Symfony表单搜索

在编辑任何输入时呈现数据表单列表?

将参数传递给 symfony 5.4 表单测试不起作用