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 :
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 :
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...
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
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.