多个嵌套的集合字段& sonata_type_collection

时间:2014-11-04 13:18:46

标签: symfony collections admin sonata

我对sonata admin bundle很新,我可以使用一些帮助。

问题:

我有一个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,但它不起作用会返回此错误: “当前字段”问题“未与管理员相关联。请为目标实体创建一个” 我已经看了这个并尝试了stackoverflow上建议的所有内容,但我无法让它工作。 我非常感谢有关此事的任何建议。

这就是目前测验的管理页面的问题和答案:

sample

正如我之前在几个版本之前提到的,在运行composer.phar更新之前,我可以添加问题和答案(我不记得版本,但是我对其他字段有一些其他问题,我很高兴得到修复,但现在我有这个问题。)

如果您有任何建议,我很乐意关注。

谢谢!

2 个答案:

答案 0 :(得分:1)

我的项目中还有一个Quizz系统,我拥有与你相同的实体。

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

  • Quizz:QuizzAdmin / QuizzController
  • 问题:QuestionAdmin / QuestionController
  • 答案:AnswerAdmin / AnswerController

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

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

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

QuizzAdmin:

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

QuestionAdmin:

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

另外,您应该考虑在Admin类中添加以下代码,以便在管理员中添加Quizz时​​触发对问答的断言验证:

class QuizzAdmin extends Admin 
{
    protected $formOptions = array(
        'cascade_validation' => true
    );
}

答案 1 :(得分:0)

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