РЕДАКТИРОВАТЬ 2018-05-22: нет ответа полностью исправлена проблема — больше не может копировать проблему, поскольку больше не имеют доступа. Не удаляется на основе это мета обсуждение
Пожалуйста, не тратьте время / усилия на создание ответа
Обсуждение в ответе @ Wilt привело меня к тому, что я знаю об использовании дискриминаторов сейчас, это может помочь будущим спрашивающим. В моем случае это помогло, но не дало ответа.
У меня есть небольшая сложная проблема, когда гидратация данных, полученных со стороны клиента, гидратируется неправильно. Я пытался решить эту проблему почти неделю, поэтому я решил спросить вас, ребята.
У нас есть это приложение, которое позволяет создавать задания для студентов. Назначения могут содержать Вопросы, Текстовые элементы, Элементы мультимедиа и многое другое. Проблема с вопросами и соответствующими ответами.
сценарий
присваивание
Вышеуказанное правильно отправляется со стороны клиента. Снимок экрана с этими данными:
Важно отметить, что, как вы можете видеть выше, Question
на самом деле GridElements
юридическое лицо. Это также могло быть Text
или же Image
, это основано на собственности type = question
который является Discriminator
.
После увлажнения данных мы получаем следующую структуру Entity:
Как видите, после гидратации данные больше не верны. Это делается во время $form->isValid()
, QuestionSheet 1
содержит первый Question
за QuestionSheet 2
и это Question
имеет первый Answer
с третьего Question
второго QuestionSheet
,
Читая полный набор гидратированных данных, я вижу, что Answers
создан для первого QuestionSheet
были сброшены Answers
со второго QuestionSheet
были продублированы и перезаписали ответы в первом листе вопросов. По сути то, что вы видите на картинке выше.
Что еще хуже
Ниже приведены все данные, которые сохраняются в базе данных после вышеупомянутого, с упомянутым сценарием из 2 списков, 5 вопросов и 9 ответов.
Итак о первом вопросе, нет Q&А слева. Вопросы второго вопросника были использованы для их перезаписи. Кроме того, есть только последние 2 Ответа, заполняющие пространство того, что должно было быть 9 !.
Кстати, запрос, возвращающий это полностью LEFT JOIN
чтобы показать все пустые данные, это все, что осталось.
Кажется, что он захватывает последний набор любых дочерних сущностей, чтобы заполнить предыдущие сущности, или что-то еще. Я заблудился.
Как это возможно?
Как я уже упоминал, я долго этим занимался, но не могу найти решение. Надеюсь, вы, ребята, можете помочь.
Если вам нужна какая-либо информация о коде, я сделаю все возможное, чтобы показать ее здесь или объяснить как можно лучше в случае использования какого-либо частного кода.
Обновление — сущности
Объект назначения
/**
* @ORM\Entity(repositoryClass="Wms\Admin\Assignment\Repository\AssignmentRepository" )
* @ORM\HasLifecycleCallbacks
* @ORM\Table(name="ass_assignment")
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
*/
class Assignment extends SeoUrl
{
//Traits and properties
/**
* @ORM\OneToMany(targetEntity="Wms\Admin\Assignment\Entity\QuestionSheet", mappedBy="assignment", cascade={"persist", "remove"}, orphanRemoval=true)
**/
protected $questionSheets;
public function __construct()
{
$this->abstractEntity_entityCategories = new ArrayCollection();
$this->questionSheets = new ArrayCollection();
$this->documents = new ArrayCollection();
}
public function __toString()
{
return (string)$this->id;
}
//More getters/setters
}
Вопросник
/**
* @ORM\Entity(repositoryClass="Wms\Admin\Assignment\Repository\QuestionSheetRepository")
* @ORM\Table(name="ass_questionsheet")
**/
class QuestionSheet extends AbstractEntity
{
/**
* @ORM\ManyToOne(targetEntity="Wms\Admin\Assignment\Entity\Assignment", inversedBy="questionSheets")
* @ORM\JoinColumn(name="assignment_id", referencedColumnName="id", onDelete="CASCADE")
**/
protected $assignment;
/**
* @ORM\OneToOne(targetEntity="Wms\Admin\LayoutGrid\Entity\Grid", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="grid_id", referencedColumnName="id")
**/
protected $grid;
public function __construct()
{
$this->gridElements = new ArrayCollection();
}
//More getters/setters
}
Сетка сущность
/**
* @ORM\Entity
* @ORM\Table(name="lg_grid")
**/
class Grid extends AbstractEntity
{
/**
* @ORM\OneToMany(targetEntity="Wms\Admin\LayoutGrid\Entity\Element\AbstractElement", mappedBy="grid", cascade={"persist", "remove"}, orphanRemoval=true)
* @ORM\OrderBy({"y" = "ASC", "x" = "ASC"})
*/
protected $gridElements;
public function __construct()
{
$this->gridElements = new ArrayCollection();
}
}
Сетка Элемент сущности
/**
* @ORM\Table(name="lg_grid_element")
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\HasLifecycleCallbacks
**/
class AbstractElement extends AbstractEntity implements GridElementInterface
{
/**
* @ORM\ManyToOne(targetEntity="Wms\Admin\LayoutGrid\Entity\Grid", inversedBy="gridElements")
* @ORM\JoinColumn(name="grid_id", referencedColumnName="id", onDelete="CASCADE")
**/
protected $grid;
public $type = ''; //This is a discriminator
}
Вопросник
/**
* @ORM\Entity
* @ORM\Table(name="lg_grid_question")
**/
class Question extends AbstractElement
{
/**
* @ORM\OneToMany(targetEntity="Wms\Admin\LayoutGrid\Entity\Element\Answer", mappedBy="question", cascade={"persist"})
*/
protected $answers;
public $type = 'question'; //Inherited property, now filled in with discriminator value
public function __construct()
{
$this->answers = new ArrayCollection();
}
}
Ответ сущности
/**
* @ORM\Entity
* @ORM\Table(name="lg_grid_answer")
**/
class Answer extends AbstractEntity
{
/**
* @ORM\ManyToOne(targetEntity="Wms\Admin\LayoutGrid\Entity\Element\Question", inversedBy="answers", cascade={"persist"})
* @ORM\JoinColumn(name="question_id", referencedColumnName="id", onDelete="CASCADE")
**/
protected $question;
public function __toSting() {
return (string) $this->getId();
}
}
Обновление 2
обновленный AbstractElement
сущность, основанная на ответе @ Wilt.
/**
* @ORM\Table(name="lg_grid_element")
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\HasLifecycleCallbacks
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({
* "abstractElement"="AbstractElement",
* "question"="Question",
* //Others
* })
**/
class AbstractElement extends AbstractEntity implements GridElementInterface
{
//Same as above
}
Это обновление создало некоторые проблемы с NonUniformCollection
который обрабатывает получение правильной сущности. Раньше это было основано на $type
имущество.
Однако, имея $type
собственность в сущности, которая имеет * @ORM\DiscriminatorColumn(name="type", type="string")
как обозначение, не допускается. Поэтому все классы, использующие дискриминатор, также были обновлены следующим образом.
const ELEMENT_TYPE = 'question'; //Overwritten from AbstractElement
/**
* @return string
*/
public function getType() //Overwritten from AbstractElement
{
return self::ELEMENT_TYPE;
}
Увы, оригинальная проблема остается.
Я не уверен, является ли это причиной вашей проблемы, но мне кажется, что ваше наследование не правильно настроено:
Вы должны объявить свой столбец дискриминатора в определениях вашей сущности как написано в документах, они не должны быть установлены как свойства, доктрина заботится об их установке в вашей базе данных:
/**
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"element"="AbstractElement", "question"="Question", "text"="TextItem", "media"="MediaItem"})
*/
class AbstractElement extends AbstractEntity implements GridElementInterface
{
//...
}
И правильно ли сопоставлена ваша абстрактная сущность? как @MappedSuperClass
?
/**
* @MappedSuperclass
*/
class AbstractEntity
{
//...
}
Это может быть частью вашего решения, пожалуйста, вернитесь с обратной связью после того, как вы обновили соответственно …
Других решений пока нет …