簡體   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