У меня проблема с Symfony 4 по проблеме, уже идентифицированной и описанной на Github (здесь: https://github.com/symfony/symfony/issues/5694#issuecomment-110398953), но я не могу найти способ применить этот ответ.
Когда я пытаюсьчтобы использовать событие формы POST_SET_DATA в форме ChildType, функция getData () дает мне нулевое значение, потому что для опции "allow_add" установлено значение true в форме ParentType, которая является CollectionType.
У меня есть 3 коллекции: Страница, Модуль и Модуль. Документ Модуль используется для встраивания коллекции форм модуля. Цель состоит в том, чтобы иметь возможность добавить несколько форм в коллекцию страниц одним запросом, следуя этой статье Symfony: https://symfony.com/doc/current/form/form_collections.html.
У меня есть 2 различных встроенных документа: тег и задача. Оба они встроены в документ модуля (EmbedOne). Я хочу настроить поле ModuleType с помощью прослушивателя события формы, так что мне просто нужночтобы установить заголовок Модуля в контроллере, и тогда Symfony знает, что ему нужно использовать TaskType или TagType в ModuleType.
Итак, во-первых, вот мой контроллер
class TaskingController extends Controller
{
/**
* The controller from which I set the module title, "task" here
*
* @Route("/{slug}/task/create", name="tasking_create")
*
* @ParamConverter("page", options={"mapping": {"slug": "slug"}})
*
* @return Response
*/
public function createTasking(DocumentManager $dm, $id, Module $module, Moduling $moduling)
{
$page = $dm->find(Page::class, $id);
$module->setTitle('task');
$moduling->addModule($module);
$page->addModuling($moduling);
$form = $this->createForm(ModulingType, $moduling);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted() {
// Form validation then redirection
}
// Render form template}
}
}
Теперь, вот мои три коллекции: страницы, модули и модули
/**
* My page document
*
* @MongoDB\Document(collection="pages")
*/
class Page
{
/**
* @MongoDB\Id(strategy="AUTO")
*/
protected $id;
/**
* @MongoDB\ReferenceMany(targetDocument="App\Document\Moduling")
*
* @var Moduling
*/
protected $moduling = array();
public function __construct()
{
$this->moduling = new ArrayCollection();
}
/**
* Get the value of id
*/
public function getId()
{
return $this->id;
}
/**
* @return Collection $moduling
*/
public function getModuling()
{
return $this->moduling;
}
/**
* @param Moduling $moduling
*/
public function addModuling(Moduling $moduling)
{
$this->moduling[] = $moduling;
}
/**
* @param Moduling $moduling
*/
public function removeModuling(Moduling $moduling)
{
$this->moduling->removeElement($moduling);
}
}
/**
* @MongoDB\Document(collection="moduling")
*/
class Moduling
{
/**
* @MongoDB\Id(strategy="AUTO")
*/
protected $id;
/**
* @MongoDB\ReferenceOne(targetDocument="App\Document\Page", storeAs="id")
*
* @var Page
*/
protected $parentPage;
/**
* @MongoDB\ReferenceMany(targetDocument="App\Document\Module", mappedBy="moduling")
*/
protected $module = array();
public function __construct()
{
$this->module = new ArrayCollection();
}
/**
* Get the value of id
*/
public function getId()
{
return $this->id;
}
public function getModule()
{
return $this->module;
}
public function addModule(Module $module): self
{
$this->module[] = $module;
}
public function removeModule(Module $module)
{
$this->module->removeElement($module);
}
/**
* Get the value of parentPage
*
* @return Page
*/
public function getParentPage()
{
return $this->parentPage;
}
/**
* Set the value of parentPage
*
* @param Page $parentPage
*
* @return self
*/
public function setParentPage(Page $parentPage)
{
$this->parentPage = $parentPage;
return $this;
}
}
/**
* @MongoDB\Document(collection="modules")
*/
class Module
{
/**
* @MongoDB\Id(strategy="AUTO")
*/
public $id;
/**
* @MongoDB\Field(type="string")
*/
public $title;
/**
* @MongoDB\ReferenceOne(targetDocument="App\Document\Moduling", inversedBy="module", storeAs="id")
*/
public $moduling;
/**
* @MongoDB\EmbedOne(targetDocument="App\Document\Task", strategy="set")
* @Assert\Valid
*/
public $task;
public function getTitle()
{
return $this->title;
}
/**
* @return self
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
public function getTask()
{
return $this->task;
}
public function setTask(Task $task = null)
{
$this->task = $task;
}
}
Мой встроенный документ Задача.Документ тега имеет ту же структуру.
/**
* @MongoDB\EmbeddedDocument
*/
class Task
{
/**
* @MongoDB\Id(strategy="AUTO")
*/
protected $id;
public function getId()
{
return $this->id;
}
}
My ModulingType, который является коллекцией ModuleType
class ModulingType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('module', CollectionType::class, [
'entry_type' => ModuleType::class,
'entry_options' => [
'label' => false,
],
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Moduling::class
]);
}
}
class ModuleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
$module = $event->getData();
$form = $event->getForm();
if ('task' == $module->getTitle()) {
$form->add('task', TaskType::class);
}
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Module::class
]);
}
}
Итак, я обнаружил проблему.Когда я пытаюсь заставить это работать, Symfony посылает мне это сообщение об ошибке: «Вызов функции-члена getTitle () on null»).Кажется, getData () ничего не получает.
На самом деле, прочитав несколько постов на Github, я понял, что источником этой проблемы была опция "allow_add", установленная на "true".И действительно, когда я устанавливаю его на «ложь», у меня нет сообщений об ошибках.Но следствием этого является то, что мой JQuery не позволяет мне дублировать форму, если я хочу, для этого необходима опция allow_add.
В загруженном мной посте Github они говорят, чторешение состоит в том, чтобы сначала написать этот код в ModuleType:
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
if (null != $event->getData()) {
}
}
Это то, что я сделал, но это ничего не меняет.Я написал это, а затем код, написанный в ModuleType, но у меня все еще есть то же сообщение об ошибке ... Возможно, я не знаю, как правильно вставить его в ModuleType.
Я надеюсь, что у кого-то есть решение,Я знаю, что все еще могу добавлять типы Tag и Task непосредственно в ModulingType, но у меня будет больше коллекций.
Большое спасибо за помощь, надеюсь, я достаточно ясен!
Приветствия