多个嵌套集合字段和奏鸣曲类型集合

Posted

技术标签:

【中文标题】多个嵌套集合字段和奏鸣曲类型集合【英文标题】:multiple nested collection fields & sonata_type_collection 【发布时间】:2014-12-31 09:37:56 【问题描述】:

我对奏鸣曲管理包还很陌生,我可以使用一些帮助。

问题:

我有一个 Quiz 实体、一个 Question 实体、一个 Answer 实体。

测验和问题之间的关系:一对多。

测验实体

/**
* @ORM\OneToMany(targetEntity="Question", mappedBy="quiz", cascade="persist", "remove")
*/
protected $questions;

问题实体

/**
* @ORM\ManyToOne(targetEntity="Quiz", inversedBy="questions", cascade="persist")
* @ORM\JoinColumn(name="quiz_id", referencedColumnName="id", nullable = false)
*/
protected $quiz;

关系问答:一对多。

问题实体

/**
* @ORM\OneToMany(targetEntity="Answer", mappedBy="question", cascade="persist", "remove")
*/
protected $answers;

回答实体

/**
* @ORM\ManyToOne(targetEntity="Question", inversedBy="answers")
* @ORM\JoinColumn(name="question_id", referencedColumnName="id")
*/
protected $question;

我需要一个表格,我可以在其中向课程添加多个问题,每个问题可以有一个或多个答案,这些答案也应该有一个真假标志。

所以基本上我需要这样的东西: mockup

到目前为止,我设法只添加了来自管理员的多个问题。实际上,在几个版本之前(奏鸣曲管理和学说),我的问题和答案都在工作。但是现在我只能添加多个问题,而无法添加任何答案。

这是我的 QuestionType 类:

<?php

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class QuestionType extends AbstractType 

    public function buildForm( FormBuilderInterface $builder, array $options )
    
        $builder
            ->add('text', 'text', array( 'required' => false, 'label' => 'question' ) )
            ->add('answers', 'collection', array(
                    'type'               => new AnswerType(),
                    'allow_add'          => true,
                    'allow_delete'       => true,
                    'by_reference'       => false,
                    'delete_empty'       => true,
                    'cascade_validation' => false,
                    'label'              => 'Answers',
                    'options'            => array( 'label' => false ),
                    'label_attr'         => array( 'class' => 'answers' ),
            ));
    


    public function getName()
    
        return 'questions';
    

    public function setDefaultOptions( OptionsResolverInterface $resolver )
    
        $resolver->setDefaults( array(
            'data_class' => MyBundle\CoreBundle\Entity\Question',
        ));
    


这是我的 AnswerType 类:

<?php

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AnswerType extends AbstractType 

    public function buildForm( FormBuilderInterface $builder, array $options )
    
        $builder
            ->add('text', 'text', array( 'required' => true, 'label' => 'answer' ) )
            ->add('correct', 'checkbox', array( 'required' => false ) );
    

    /**
     * @inheritdoc
     */
    public function getName()
    
        return 'answers';
    

    public function setDefaultOptions( OptionsResolverInterface $resolver )
    
        $resolver->setDefaults( array(
            'data_class' => 'MyBundle\CoreBundle\Entity\Answer',
        ));
    


这是我的 QuizAdmin 课程:

<?php 

use MyBundle\CoreBundle\Form\QuestionType;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;

class QuizAdmin extends Admin


    // Fields to be shown on create/edit forms
    protected function configureFormFields( FormMapper $formMapper )
    
        $formMapper
            ->add('title', 'text', array( 'label' => 'Quiz Title' ) )
            ->add('description', 'textarea', array( 'label' => 'Quiz Description' ) )
            ->add('private', 'checkbox', array('required' => false ) )
            ->add('questions', 'collection', array(
                    'type'               => new QuestionType(),
                    'allow_add'          => true,
                    'allow_delete'       => true,
                    'cascade_validation' => false,
                    'by_reference'       => false,
                    'delete_empty'       => true,
                    'options'            => array( 'label' => false ),
            ));
    

    // Fields to be shown on filter forms
    protected function configureDatagridFilters( DatagridMapper $datagridMapper )
    
        $datagridMapper
            ->add( 'title' );
    

    // Fields to be shown on lists
    protected function configureListFields( ListMapper $listMapper )
    
        $listMapper
            ->addIdentifier( 'title' );
    

我也尝试过使用 sonata_type_collection 但它不起作用,它返回此错误: “当前字段“问题”未链接到管理员。请为目标实体创建一个“ 我已经查看了这个并尝试了***上建议的所有内容,但我无法让它工作。 我非常感谢任何关于这个问题的建议。

这是测验的管理页面当前的样子,其中包含问题和答案:

sample

正如我在运行 composer.phar update 之前的几个版本之前提到的那样,我可以添加问题和答案(我不记得版本,但后来我遇到了一些独特字段的其他问题,我很高兴得到了修复,但现在我遇到了这个问题)。

如果您有任何建议,我很乐意遵循。

谢谢!

【问题讨论】:

【参考方案1】:

嗨,我的朋友们,这是我的第一个答案,我希望它有用。 我怎样才能为几个 lewel 做嵌套收集: 1) 创建 AnswerType 2) 不要创建 QuestionType 3) 在 QuestionAdmin 中使用集合 AnswerType 4) 在 QuizAdmin 中使用 sonata_type_collection 作为问题实体

【讨论】:

【参考方案2】:

我的项目中还有一个测验系统,我的实体和你一样。

您必须为每个实体创建控制器和管理员:

测验:QuizzAdmin / QuizzController 问题:QuestionAdmin / QuestionController 答案:AnswerAdmin / AnswerController

这将解决您的错误:当前字段“问题”未链接到管理员。请为目标实体创建一个。

我使用 sonata_type_collection 作为字段类型,您必须使用此要点:https://github.com/sonata-project/SonataAdminBundle/pull/1971/files,否则您将无法添加答案。

您只需要更改您的字段答案以匹配我的课程中的答案。

测验管理员:

class QuizzAdmin extends Admin

    protected function configureListFields(ListMapper $listMapper)
    
         $formMapper->add('questions', 'sonata_type_collection',
             array(
                 'by_reference' => false
             ),
             array(
                 'edit' => 'inline',
                 'inline' => 'table'
            )
        );
    

问题管理员:

class QuestionAdmin

    protected function configureFormFields(FormMapper $formMapper)
    
        $formMapper->add('answers', 'sonata_type_collection',
            array(
                'by_reference' => false
             ),
             array(
                 'edit' => 'inline',
                 'inline' => 'table'
            )
        );
    

您还应该考虑在您的管理员类中添加以下代码,以便在您在管理员中添加测验时触发您对问题和答案的断言验证:

class QuizzAdmin extends Admin 

    protected $formOptions = array(
        'cascade_validation' => true
    );

【讨论】:

嗨,我正在使用嵌套的“sonata_type_collection”做与此非常相似的事情,但我遇到了一个问题,我正在使用答案中提到的要点。当我只有一个集合时,一切都显示得很好,但是当我嵌套它们时,第一个集合的孩子就会消失。你知道为什么吗(你的quizadmin类也有错误,你使用了configureListFields方法,它应该是configureFormFields,并且编辑队列已满)

以上是关于多个嵌套集合字段和奏鸣曲类型集合的主要内容,如果未能解决你的问题,请参考以下文章

在奏鸣曲类型集合中创建新行后如何添加 javascript?

访问视图中的嵌套表单字段(嵌入表单集合)

Mybatis resultMap 嵌套集合

来自多个集合的 $lookup 和嵌套输出

spring mongodb - 排序嵌套集合字段

将复杂对象与嵌套集合放在一起