繁体   English   中英

将带有“ choice_list”的表格更新为Symfony> = 2.8

[英]Update Form with 'choice_list' to Symfony >= 2.8

我想将表单类更新为Symfony2.8(然后更新为Symfony3)。 现在,除了一个不再支持的属性choice_list外,该表单已转换。 而且我不知道该怎么做。

我具有以下也定义为服务的表单类型:

class ExampleType extends AbstractType
{

    /** @var Delegate */
    private $delegate;

    public function __construct(Delegate $delegate)
    {
        $this->delegate = $delegate;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('list', ChoiceType::class, array(
            'choice_list' => new ExampleChoiceList($this->delegate),
            'required'=>false)
        );
    }

    public function configureOptions(OptionsResolver $resolver)
    {
            $resolver->setDefaults(array(
                'data_class' => 'ExampleClass',
            ));
    }
}

对于选择列表,我有以下课程:

class ExampleChoiceList extends LazyChoiceList
{

    /** @var Delegate  */
    private $delegate;

    public function __construct(Delegate $delegate)
    {
        $this->delegate = $delegate;
    }


    /**
     * Loads the choice list
     * Should be implemented by child classes.
     *
     * @return ChoiceListInterface The loaded choice list
     */
    protected function loadChoiceList()
    {
        $persons = $this->delegate->getAllPersonsFromDatabase();
        $personsList = array();
        foreach ($persons as $person) {
            $id = $person->getId();
            $personsList[$id] = (string) $person->getLastname().', '.$person->getFirstname();
        }
        return new ArrayChoiceList($personsList);
    }


}

类ExampleChoiceList生成选择列表的方式,直到现在我都可以使用。 但是不再支持属性choice_list ,我的问题是“如何在不进行过多工作的情况下进行转换?”。 我读到应该使用简单的choice但是如何在Symfony 2.8中获得所需的信息(数据库中的特定标签)。 我希望有人能帮助我。

是的,SYmfony 2.8不推荐使用“ choice_list”,但是您可以改用“ choices”,它也接受数组。 文档

choices选项是一个数组,其中数组键是项目的标签,而数组值是项目的值。

您必须要注意的是,在Symfony 3.0中,键和值是相反的,在Symfony 2.8中,建议的方法是使用新的相反顺序,并指定'choices_as_values'=> true。

因此,在表单类型中:

$builder->add('list', ChoiceType::class, array(
               'choices' => new ExampleChoiceList($this->delegate),
               'choices_as_values' => true,
               'required'=>false));

在ExampleChoiceList中:

protected function loadChoiceList()
    {
        $persons = $this->delegate->getAllPersonsFromDatabase();
        $personsList = array();
        foreach ($persons as $person) {
            $id = $person->getId();
            $personsList[(string) $person->getLastname().', '.$person->getFirstname()] = $id; // <== here
        }
        return new ArrayChoiceList($personsList);
    }

更新:

好的,所以我建议您根本不使用ChoiceType,而要使用EntityType,因为您似乎从数据库中获取了所有“人”。 要显示“姓氏,名字”作为标签,请使用“ choice_label”选项。 假设您的实体称为“人员”:

$builder->add('list', EntityType::class, array(
    'class' => 'AppBundle:Person',
    'choice_label' => function ($person) {
        return $person->getLastName() . ', ' . $person->getFirstName();
    }
));  

通过使用ChoiceListInterface您几乎可以ChoiceListInterface

我建议您更改ExampleChoiceList来实现Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface ,它需要实现3种方法:

<?php
// src/AppBundle/Form/ChoiceList/Loader/ExampleChoiceLoader.php

namespace AppBundle\Form\ChoiceList\Loader;

use Acme\SomeBundle\Delegate;
use Symfony\Component\Form\ArrayChoiceList;
use Symfony\Component\Form\Loader\ChoiceLoaderInterface;

class ExampleChoiceLoader implements ChoiceLoaderInterface
{
    /** $var ArrayChoiceList */
    private $choiceList;

    /** @var Delegate  */
    private $delegate;

    public function __construct(Delegate $delegate)
    {
        $this->delegate = $delegate;
    }

    /**
     * Loads the choice list
     * 
     * $value is a callable set by "choice_name" option
     *
     * @return ArrayChoiceList The loaded choice list
     */
    public function loadChoiceList($value = null)
    {
        if (null !== $this->choiceList) {
            return $this->choiceList;
        }

        $persons = $this->delegate->getAllPersonsFromDatabase();
        $personsList = array();
        foreach ($persons as $person) {
            $label = (string) $person->getLastname().', '.$person->getFirstname();
            $personsList[$label] = (string) $person->getId();
            // So $label will be displayed and the id will be used as data
            // "value" will be ids as strings and used for post
            // this is just a suggestion though
        }

        return $this->choiceList = new ArrayChoiceList($personsList);
    }

    /**
     * {@inheritdoc}
     *
     * $choices are entities or the underlying data you use in the field
     */
    public function loadValuesForChoices(array $choices, $value = null)
    {
        // optimize when no data is preset
        if (empty($choices)) {
            return array();
        }

        $values = array();
        foreach ($choices as $person) {
            $values[] = (string) $person->getId();
        }

        return $values;
    }

    /**
     * {@inheritdoc}
     * 
     * $values are the submitted string ids
     *
     */
    public function loadChoicesForValues(array $values, $value)
    {
        // optimize when nothing is submitted
        if (empty($values)) {
            return array();
        }

        // get the entities from ids and return whatever data you need.
        // e.g return $this->delegate->getPersonsByIds($values);
    }
}

将加载程序和类型都注册为服务,以便将它们注入:

# app/config/services.yml

services:
    # ...
    app.delegate:
        class: Acme\SomeBundle\Delegate

    app.form.choice_loader.example:
        class: AppBundle\Form\ChoiceList\Loader\ExampleChoiceLoader
        arguments: ["@app.delegate"]

    app.form.type.example:
        class: AppBundle\Form\Type\ExampleType
        arguments: ["@app.form.choice_loader.example"]

然后更改表单类型以使用加载程序:

<?php
// src/AppBundle/Form/Type/ExampleType.php

namespace AppBundle\Form\Type;

use AppBundle\Form\ChoiceList\Loader\ExampleChoiceLoader;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class ExampleType extends AbstractType
{
    /** @var ExampleChoiceLoader */
    private $loader;

    public function __construct(ExampleChoiceLoader $loader)
    {
        $this->loader = $loader;
    }

    public function buildForm(FormBuilderInterface $builder, array $options = array())
    {
        $builder->add('list', ChoiceType::class, array(
            'choice_loader' => $this->loader,
            'required' => false,
        ));
    }

    // ...

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM