根据条目的数据修改CollectionType中的entry_options

时间:2018-06-28 19:00:24

标签: symfony symfony-forms

我有一个带有收藏夹的Symfony表格。用户可以在组织中添加或删除用户(为简单起见,仅为示例)。但是,我要防止人们从组织中删除某些用户。假设:管理员不能被删除,但是他们的名字仍然可以更改。

这是我现在所拥有的:

class OrganisationType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add(
            'users',
            CollectionType::class,
            [
                'required' => FALSE,
                'entry_type' => UserType::class,
                'label' => 'Users',
                'show_legend' => FALSE,
                'entry_options' => [
                    'label_render' => FALSE,
                    'data_class' => User::class,
                ],
                'widget_add_btn' => ['label' => 'Add user'],
                'by_reference' => FALSE,
                'allow_add' => TRUE,
                'allow_delete' => TRUE,
                'prototype' => TRUE,
            ]
        );
    }
}

class UserType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add(
                'name',
                TextType::class,
                ['required' => TRUE]
            )
            ->add(
                'email',
                TextType::class,
                ['required' => TRUE]
            );
    }
}

我已经读过Form Events,但是当尝试在UserType中使用表单事件时,似乎没有办法修改Collection中的条目:

$builder->addEventListener(
        FormEvents::POST_SET_DATA,
        function(FormEvent $event) {
            $user = $event->getData();
            $form = $event->getForm();

            if ($user->isAdmin()) {
                //maybe some logic here? But what?
            }
        }
)

我可以根据条目的数据修改entry_options吗?

1 个答案:

答案 0 :(得分:0)

如果我正确理解这一点,可以通过听PRE_SUBMIT上的POST_SUBMITOrganisationType事件来完成。

我首先要记住PRE_SUBMIT上的用户ID,然后在POST_SUBMIT上将现有集合与上一个集合进行比较。像这样:

<?php
class OrganisationType extends AbstractType {

    private $preSubmitAdminsIds = [];

    public function buildForm(FormBuilderInterface $builder, array $options) {
        // ....

        $adminIds = $this->preSubmitAdminsIds;

        $builder
        ->addEventListener('PRE_SUBMIT', function(FormEvent $event) use (&$adminIds){ // ! Note the reference pass
            $org = $event->getData();
            $users = $org->getUsers();

            foreach ($users as $u){
                if ($u->isAdmin()){
                    $adminIds[] = $u->getId(); // I guess you do have some sort of id
                }
            }
        })
        ->addEventListener('POST_SUBMIT', function(FormEvent $event) use (&$adminIds) { // ! Note the reference pass
            $org = $event->getData();
            $users = $org->getUsers();
            $newAdminIds = [];

            foreach ($users as $u){
                if ($u->isAdmin()){
                    $newAdminIds[] = $u->getId();
                }
            }

            if (!empty(array_diff($adminIds, $newAdminIds))){
                $event->getForm()->get('users')->addError("You cannot remove admins!");
            }
        });

        // ....
    }
} 

笔记夫妇:

  1. 用户应具有一些不变的ID(getId()
  2. 我可能会将提交逻辑提交给验证者,但是我的逻辑与上面的非常相似。
  3. 请注意,我将adminIds的引用传递给了匿名函数。如果这对您来说太脏了,您实际上可以传递private方法参考。这也使类字段访问更加容易。
  4. 根据您的实体实现,您应该选择对$org->getUsers()进行null安全检查...

希望这对您有帮助...