Symfony - 很多人没有得救

时间:2016-05-25 13:36:01

标签: php symfony

情景

我有两个与manyToMany关系链接在一起的实体。

实体

  1. User
  2. Interest
  3. 因此,在用户的个人资料表单中,有一个名为Interests的字段,使用select2呈现。

    现在,用户可以根据需要选择任意数量的兴趣,并且在保存原则时,可以很好地将所选兴趣保存在链接表中。当我重新加载个人资料页面时,我可以看到我已经选择的兴趣。

    enter image description here

    问题

    虽然表单字段与Interest实体

    相关联
                $form->add('interest', EntityType::class, array(
                        'class' => 'AppBundle\Entity\Interest',
                        'multiple' => true,
                        'expanded' => false,
                        'by_reference' => false)
    

    用户还可以在前端和后端Tagging Support的帮助下添加Interest表中不存在的自己的兴趣,以保存我Form Event Subscriber所拥有的信息检查用户提交的任何兴趣是否存在于Interest表中的地方添加它们并且它在这里我得到以下异常

        Message
               This value is not valid. 
    
        Origin
               interest 
    
       Cause
                Symfony\Component\Validator\ConstraintViolation
                Object(Symfony\Component\Form\Form).children[interest] = [0 => 1, 1 => 4, 2 => 7, 3 => www]
    
    
        Caused by:
                Symfony\Component\Form\Exception\TransformationFailedException
                Unable to reverse value for property path "interest": Could not find all matching choices for the given values
    
    
        Caused by:
                Symfony\Component\Form\Exception\TransformationFailedException
                Could not find all matching choices for the given values
    

    以下是事件订阅者代码

    namespace AppBundle\Form\EventListener;
    
    
    use AppBundle\Entity\Interest;
    use Doctrine\ORM\EntityManager;
    use Symfony\Component\Form\FormEvent;
    use Symfony\Component\Form\FormEvents;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
    
    
    class AddProfileFieldSubscriber implements EventSubscriberInterface
    {
        protected $authorizationChecker;
    
        protected $em;
    
        function __construct(AuthorizationChecker $authorizationChecker, EntityManager $em)
        {
            $this->authorizationChecker = $authorizationChecker;
            $this->em = $em;
        }
    
        public static function getSubscribedEvents()
        {
            // Tells the dispatcher that you want to listen on the form.pre_set_data
            // event and that the preSetData method should be called.
            return array(
                FormEvents::PRE_SUBMIT => 'onPreSubmit'
                );
        }
    
    
        /**
         * @param FormEvent $event
         */
        public function onPreSubmit(FormEvent $event){
    
            $interestTags = $event->getData();
            $interestTags = $interestTags['interest'];
            foreach($interestTags as $interestTag){
                $interest = $this->em->getRepository('AppBundle:Interest')->findOneBy(array('id' => $interestTag));
                if(!$interest){
                    $newInterest = new Interest();
                    $newInterest->setName($interestTag);
                    $this->em->persist($newInterest);
                    $this->em->flush();
                }
            }
    
        }
    }
    

    尝试

    我通过添加choice_value

    将表单代码更新为以下内容
            $form->add('interest', EntityType::class, array(
                    'class' => 'AppBundle\Entity\Interest',
                    'multiple' => true,
                    'expanded' => false,
                    'by_reference' => false,
                    'choice_value' => 'name'
                )
            );
    

    我从

    更改了事件订阅者中的查询
    $interest = $this->em->getRepository('AppBundle:Interest')->findOneBy(array('id' => $interestTag));
    

    $interest = $this->em->getRepository('AppBundle:Interest')->findOneBy(array('name' => $interestTag));
    

    这首先完美无缺,但是当我重新加载个人资料页面时,我的兴趣字段显示为空

    enter image description here

    它显得空的原因是因为(我的假设)id="select2-user_interest-result-5z18-Education"我认为需要看起来像id="select2-user_interest-result-5z18-66"

    <ul class="select2-results__options" role="tree" aria-multiselectable="true" id="select2-user_interest-results"
    aria-expanded="true" aria-hidden="false">
    <li class="select2-results__option" id="select2-user_interest-result-5z18-Education" role="treeitem"
        aria-selected="false">Education
    </li>
    <li class="select2-results__option" id="select2-user_interest-result-rdka-History" role="treeitem"
        aria-selected="false">History
    </li>
    <li class="select2-results__option select2-results__option--highlighted"
        id="select2-user_interest-result-lfq4-Architecture" role="treeitem" aria-selected="false">Architecture
    </li>
    <li class="select2-results__option" id="select2-user_interest-result-qqiq-Entrepreneurship" role="treeitem"
        aria-selected="false">Entrepreneurship
    </li>
    <li class="select2-results__option" id="select2-user_interest-result-qutx-Technology" role="treeitem"
        aria-selected="false">Technology
    </li>
    <li class="select2-results__option" id="select2-user_interest-result-sfx4-Engineering" role="treeitem"
        aria-selected="false">Engineering
    </li>
    

    我交叉检查了兴趣表中的数据,我可以看到用户添加的新兴趣之前不存在,所以它的工作但在前端没有显示。出于好奇,我删除了choice_value,然后重新加载了个人资料页面,我可以看到新的兴趣

    enter image description here

    如果有任何事情可以让我朝着正确的方向前进并让我知道我错过了什么以及如何让它发挥作用,我将非常感激。

1 个答案:

答案 0 :(得分:0)

您无法以EntityType扩展ChoiceType来执行此操作,但不允许在选项列表中添加新值。

您应该在食谱http://symfony.com/doc/current/cookbook/form/form_collections.html

中使用CollectionType

要在代码中进行正确的选择,您还必须在视图中插入所有兴趣的完整列表以及表单。

然后你的观点应该是:

<select name='{{ form.interest.vars.full_name }}' id="{{ form.interest.vars.id }}" class='select2'>
    {% for interestList as interestItem %}
        <option value='{{ interestItem.id }}' {% if some_logic_to_check_whether_the_item_is_selected  %}selected='selected'{% endif %} >{{ interestItem.name }}</option>
    {% endfor %}
</select>