Документ с EmbedMany в виде формы (Symfony 3) - PullRequest
0 голосов
/ 15 марта 2020

У меня есть документ

/**
 * @ODM\Document
 */
class Result
{
    /**
     * @var int $id
     * @ODM\Id
     */
    protected $id;

    /**
     * @var string $name
     * @ODM\Field(type="string")
     */
    protected $name;

    /**
     * @var UserComment[] $userComments
     * @ODM\EmbedMany(targetDocument="UserComment")
     */
    protected $userComments;
}

/** @ODM\EmbeddedDocument() */
class UserComment {
    public $addedBy;
    public $createdAt;
    public $comment;
}

Я хочу создать форму, которая позволит мне добавлять новые комментарии пользователей. Но он будет иметь $comment как TextAreaType. Остальные 2 поля должны быть добавлены автоматически.

Я использовал тип коллекции следующим образом:

class ResultForm extends AbstractType
{
    /**
     * buildForm
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('userComments', CollectionType::class, [
            'entry_type' => UserCommentType::class,
            'required' => false,
            'allow_add' => true,
            'label' => false,
            'delete_empty' => true,
            'prototype' => true,
            'entry_options' => [
                'attr' => [
                    'class' => 'user-comment-widget'
                ],
                'label' => false,
            ]
        ]);

        $builder->add('submit', SubmitType::class);
    }

И добавил также UserCommentType:

class UserCommentType extends AbstractType
{
    /**
     * @var TokenStorage
     */
    private $tokenStorage;

    public function __construct(TokenStorage $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    /**
     * buildForm
     * @param FormBuilderInterface $builder
     * @param array $options
     * @throws \Exception
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $now = new \DateTime('now');
        $builder->add('comment', TextareaType::class, [
                'label' => false,
            ])
            ->add('addedBy', HiddenType::class, [
                'data' => $this->tokenStorage->getToken()->getUser()->getUsername(),
            ])
            ->add('createdAt', HiddenType::class, [
                'data' => $now->format('Y-m-d H:i:s')
            ]);
    }

После получения куча исключений / ошибок и т. д. c Я подумал, что должен быть более простой способ сделать это. Это не работает, так как UserCommentType по какой-то причине не имеет доступа к исходным данным, хотя я использую это для инициализации ResultForm:

$form = $this->createForm(ResultForm::class, $result);

1 Ответ

0 голосов
/ 17 марта 2020

Чтобы получить доступ к значениям в форме коллекции, вы должны использовать слушатели. Добавив в форму прослушиватель PRE_SET_DATA, вы можете изменить эти значения.

Документация

$builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));

Теперь функция вызывается слушателем. Это будет выполнять итерацию по каждому элементу в коллекции, поэтому вы можете добавить туда свой код.

public function onPreSetData(FormEvent $event) {

    $entity = $event->getData();
    $form = $event->getForm();

    if ($entity) {
        $form->add('comment', TextareaType::class, [
            'label' => false,
            ])
            ->add('addedBy', HiddenType::class, [
                'data' => $this->tokenStorage->getToken()->getUser()->getUsername(),
            ])
            ->add('createdAt', HiddenType::class, [
                'data' => $now->format('Y-m-d H:i:s')
            ]);
    }
}

Обязательно добавьте предложение if, если это необходимо, поскольку первая итерация будет заключаться в создании прототипа формы коллекции и вы, возможно, не захотите, чтобы он имел предварительно установленные значения.

...