如何定义Symfony表单选择选项,以便可以在树枝模板中轻松访问



似乎有很多可能的方法可以做到这一点,但似乎没有理想。

数组解决方案

使用相同的字符串作为选择值和标签(数组键和值)

// ContactType.php
$builder->add('gender', 'choice', array(
    'choices'  => array(
        'Male'   => 'Male', 
        'Female' => 'Female',
    ),
));

现在在树枝模板上,例如,确认页可以输出如下:

// show.html.twig
{{ gender }}

PROS:

  • 易于实现
  • 模板很容易创建,设计师可以理解

cons:

  • 如果已提交的表单的数据存储在数据库中,则性别选项将存储为完整字符串MaleFemale,而不是机器友好值,例如'm''f'01,似乎不好的编程实践

选择解决方案

为选择选项使用机器友好的值,并创建一个树枝过滤器以在模板中读取这些滤镜。

// GenderChoiceList.php
class GenderChoiceList extends LazyChoiceList 
{
    protected function loadChoiceList()
    {
        $choices = array(
            0 => 'm', 
            1 => 'f',
        );
        $labels = array(
            0 => 'Male', 
            1 => 'Female',
        );
        return new ChoiceList($choices, $labels);
    }
}
// ContactType.php
$builder->add('gender', 'choice', array(
    'choice_list'  => new GenderChoiceList(),
));
// TwigExtension.php
$filter = new Twig_SimpleFilter('getChoice', function ($value) {
    $genderChoiceList = new GenderChoiceList();
    $choices = $genderChoiceList->getChoicesForValues(array($value))
    return $choices[0];
});
// show.html.twig
{{ gender|getChoice }}

PROS:

  • 现在,性别以更明智的格式存储在数据库中

cons:

  • 更多的代码,因为它应该是微不足道的
  • 模板中使用树枝过滤器的使用对于设计师而言尚不清楚且显而易见

学说解决方案

为选择选项创建相关实体。

// src/AppBundle/Entity/Gender.php
// ...
class Gender
{
    /**
     * @ORMColumn(type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORMColumn(type="string", length=100)
     */
    protected $name;
    public function __toString()
    {
        return $this->name;
    }
    public function getName()
    {
        return $this->name;
    }
    // ...
}

// src/AppBundle/Entity/Contact.php
// ...
class Contact
{
    // ...
    /**
     * @ORMManyToOne(targetEntity="Gender", inversedBy="contacts")
     * @ORMJoinColumn(name="gender_id", referencedColumnName="id")
     */
    protected $gender;
}
// ContactType.php
$builder->add('gender', 'entity', array(
    'class' => 'AppBundle:Gender',
));
// show.html.twig
{{ gender }} or {{ gender.name }}

PROS:

  • 性别以更明智的格式存储在数据库中
  • 选择也存储在数据库中,这似乎是这种数据的明智场所
  • 模板代码简单明了

cons:

  • 有很多觉得应该很琐碎的代码
  • 呈现模板时,除非编写自定义查询,否则还会有其他数据库调用,这再次是代码

结论问题

有更好的选择吗?简单的东西没有缺点?

更新:

也许这可以在Contact实体的getGender()方法中最好地处理。

// Contact.php
class Contact
{
    // ...
    public function getGender()
    {
        if (null === $this->gender) {
            return $this->gender;
        }
        $choices = array(
            'm' => 'Male',
            'f' => 'Female',
        );
        return $choices[$this->gender];
    }
    // ...
}

输出完整的字符串MaleFemale如下:

// show.html.twig
{{ gender }}

我使用chocelist/twigextension方法的原因有两个原因:

  • 一般来说,实体不必知道显示逻辑
  • 在Twigextension中集中检索逻辑意味着将来很容易将转换应用于您的所有列表

可以轻松地获得选择值,然后定义它们,以便在类型中访问它们:

class GenderChoiceList extends ChoiceList
{
    public $keyValues = ['m' => 'Male', 'f' => 'Female'];
    public function __construct()
    {
        parent::__construct(array_keys($this->keyValues), array_values($this->keyValues));
    }
}

使您的过滤器或功能了解应检索值的选择形式(我通常使用函数):

class ChoiceTwigExtension extends Twig_Extension
{
    public function getFunctions()
    {
        return [
            new Twig_SimpleFunction('choice', array($this, 'choiceFunction'))
        ];
    }
    public function choiceFunction($class, $choice)
    {
        $choiceList = new $class;
        return $choiceList->keyValues[$choice];
    }
    ...

在模板中,通过类和标签的键:

{{ choice('Bundle\ChoiceList\GenderChoiceList', gender) }}

所以,类似于Twig的constant的方式。

说到常数,既然PHP 5.6支持数组consts。

旁边:我喜欢将所有列表作为不同的选择性类别。在项目开始时,这似乎有些过分杀伤,但是随着系统的发展并形成繁殖,生活变得更加轻松。

相关内容

  • 没有找到相关文章

最新更新