Question

I am using Symfony2 and I have a hierarchy of classes. The hierarchy is pretty simple, I have a Question (the parent) and many different sub-questions. Using Sonata, I want to be able to create different types of questions, that are sub-questions. To do so, I created a hierarchy of classes as follows :

Hippy\ScavengerHuntBundle\Entity\Question:
    type: entity
    table: null
    inheritanceType: JOINED
    discriminatorColumn:
        name: subClass
        type: string
    discriminatorMap:
        blurredMultipleChoiceQuestion: BlurredMultipleChoiceQuestion
        blurredTextQuestion: BlurredTextQuestion
        slidingPuzzleQuestion: SlidingPuzzleQuestion
        associationQuestion: AssociationQuestion
        trueOrFalseQuestion: TrueOrFalseQuestion
        lettersInOrderQuestion: LettersInOrderQuestion
        shortTextQuestion: ShortTextQuestion
        multipleChoiceQuestion: MultipleChoiceQuestion
        sentenceGapQuestion: SentenceGapQuestion
    fields:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
        title:
            type: string
            length: 255
        position:
            type: integer  



    lifecycleCallbacks: {  }

And I'll show you one example of a subclass

Hippy\ScavengerHuntBundle\Entity\LettersInOrderQuestion:
    type: entity
    table: null
    fields:
        description:
            type: text


    lifecycleCallbacks: {  }

<?php

namespace Hippy\ScavengerHuntBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * LettersInOrderQuestion
 */
class LettersInOrderQuestion extends Question
{
    /**
     * @var string
     */
    private $description;


    /**
     * Set description
     *
     * @param string $description
     * @return LettersInOrderQuestion
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    {
        return $this->description;
    }


}

At this point, everything seems to be set up properly (the database and the php classes).

Now, I want to integrate this to SonataAdmin, so I added the following in the services

sonata.admin.question:
    class: Hippy\ScavengerHuntBundle\Admin\QuestionAdmin
    tags:
        - { name: sonata.admin, manager_type: orm, group: "Questions", label: "Question" }
    arguments:
        - ~
        - Hippy\ScavengerHuntBundle\Entity\Question
        - ~
    calls:
        - [ setTranslationDomain, [HippyScavengerHuntBundle]]
        - [ setSubClasses, [{lettersInOrderQuestion : "Hippy\ScavengerHuntBundle\Entity\LettersInOrderQuestion"}]]

And I created a class QuestionAdmin.php

<?php
// src/Acme/DemoBundle/Admin/PostAdmin.php

namespace Hippy\ScavengerHuntBundle\Admin;


use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;

use Hippy\ScavengerHuntBundle\Entity\LettersInOderQuestion;


class QuestionAdmin extends Admin
{
    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper)
    {

        $subject = $this->getSubject();

        var_dump($subject);
        //exit();


        if ($subject instanceof LettersInOrderQuestionAdmin) {
            $formMapper->add('description', 'text');
        }



    }



    // 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')
        ;
    }
}

At this point, one thing that is cool is that Sonata admin seems to recognize that I'm dealing with subclasses, take a look : enter image description here

My problem is that when I try to create a lettersInOrderQuestion object, it is not recognized as a lettersInOrderQuestion but only as a Question. See here : enter image description here

We can see, first via the var_dump and second because the form description is not show, that the object passed is a Question and not a LettersInOrderQuestion, even though the url is

/admin/hippy/scavengerhunt/question/create?subclass=lettersInOrderQuestion

I'm running out of ideas....

Edit1:

In Question AdminClass, in the configureFormFields method, I added

var_dump($this->getSubClasses());

and the result was the following:

array (size=1)

'lettersInOrderQuestion' => string 'Hippy\ScavengerHuntBundle\Entity
ettersInOrderQuestion' (length=56)

Therefore, it looks like there is an error in the parsing of the entity class as the name gets mixed up...

Was it helpful?

Solution

First, there is a typo in your namespace in QuestionAdmin, it should probably be

use Hippy\ScavengerHuntBundle\Entity\LettersInOrderQuestion;

and not (Oder instead of Order"

use Hippy\ScavengerHuntBundle\Entity\LettersInOderQuestion;

Secondly, also in QuestionAdmin, you are mixing the Admin class and the entity class. See here, you have:

if ($subject instanceof LettersInOrderQuestionAdmin) {

it should be, according to your code:

if ($subject instanceof LettersInOrderQuestion) {

Finally, in SonataAdmin, it looks like if you put only one subclass, the class never gets active. You have to put at least two subClasses, if not, the subclass never gets active, see here :

public function hasActiveSubClass()
{
    if (count($this->subClasses) > 1 && $this->request) {
        return null !== $this->getRequest()->query->get('subclass');
    }

    return false;
} 

An issue has been opened here : https://github.com/sonata-project/SonataAdminBundle/issues/1945

OTHER TIPS

Sonata admin takes as second constructor argument entity class. This class is saved in private variable of parent SonataAdminClass and can not be changed. This class use Model manager to create new instance of this entity class, in your case Question.

This Question object returns admin by method getSubject();

Admin knows nothing about your intention to use entity LettersInOderQuestion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top