php 如何在Symfony 6中为不存在的项目生成多对多关系的FormType?

cgh8pdjw  于 2023-01-08  发布在  PHP
关注(0)|答案(1)|浏览(98)

我有ArticleTag实体之间简单的多对多关系,我想用FormType创建一个新的文章,并关联标签,但情况是:我想关联可能尚不存在的标记

public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('title', TextType::class)
            ->add('tags', EntityType::class, [
                'class' => Tag::class,
                'multiple' => true
            ])
        ;
    }

此表单类型生成一个多选表单现有的标签只。但我想有一个<textarea>字段,用户可以把现有的和不存在的标签。然后在表单提交后,现有的标签将与新的文章相关联,而不存在的标签首先将被添加,然后与新的文章相关联。
我刚到Symfony的世界,所以如果我的问题是微不足道的,请原谅。

os8fio9y

os8fio9y1#

首先,对不起我的英语。我会给予你一个基于EmbarazadaEtiquetaAspectoEmbarazada实体(多对多关系)和tetranz /select2entity-bundle的使用的例子。这个想法是注册一个孕妇和associate她的许多标签,在输入的文本标签名称不存在的情况下,它可以从Embarazada表单类型插入。
EmbarazadaType表单类汇总:

namespace App\Form;

use App\Entity\EtiquetaAspectoEmbarazada;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;

class EmbarazadaType extends AbstractType
{

    public function __construct(private readonly ManagerRegistry $em, private readonly array $formParams)
    {

    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('nombre', TextType::class, [
                    'label' => 'Nombre y Apellidos*',
                ])

                ->add('otrosAspectos', Select2EntityType::class, [
                    'label' => 'Aspectos de interés',
                    'label_attr' => ['class' => 'text-secondary'],
                    'class' => EtiquetaAspectoEmbarazada::class,
                    'remote_route' => 'embarazada_encontrarEtiquetaAspectos', // an action to search tags by text typed.
                    'primary_key' => 'id',
                    'text_property' => 'text',
                    'multiple' => true,
                    'allow_clear' => false,
                    'delay' => 250,
                    'cache' => false,
                    'minimum_input_length' => 3,
                    'scroll' => true,
                    'page_limit' => $this->formParams['limite_resultados_etiquetas'],
                    'language' => 'es',
                    'width' => '100%',
                    'placeholder' => '',
                    'allow_add' => [
                        'enabled' => true,
                        'new_tag_text' => '(NUEVA)',
                        'new_tag_prefix' => '**',
                        'tag_separators' => '[",", ";", " "]'
                    ],
        ]);

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Embarazada::class,
            'attr' => ['id' => 'embarazadaForm', 'autocomplete' => 'off'],
        ]);
    }

}

行动的逻辑captarAction(注册pregnam女人)寻找里面的评论:

public function captarAction(Request $request, ManagerRegistry $manager, UuidEncoder $uuidEncoder, LoggerInterface $logger): Response
    {
        if ($request->isXmlHttpRequest()) {
            try {               

                $nuevaEmbarazada = new Embarazada();                

                $form = $this->createForm(EmbarazadaType::class, $nuevaEmbarazada, [
                    'action' => $this->generateUrl('embarazadas_captar', ['cmfId' => $uuidEncoder->encode($estructuraOrganizativa->getIdPublico())]),
                    'method' => Request::METHOD_POST,
                ]);

                if ($request->isMethod(Request::METHOD_POST)) {
                    $form->handleRequest($request);

                    if ($form->isSubmitted() && $form->isValid()) {

                        
                        $conn = $em->getConnection();
                        $conn->beginTransaction();
                        try {
                            
                            /**
                             * All tags present in the collection otrosAspectos with empty id, are takens as news, so need to remove '**' that indicate
                             * in that case the end of a new tag and persist, checking first if not exist in database another tag with similar name without '**'.
                            **/

                            foreach ($nuevaEmbarazada->getOtrosAspectos() as $etiqueta) {
                                if (empty($etiqueta->getId())) {
                                    $etiquetaSimilar = $manager->getRepository(EtiquetaAspectoEmbarazada::class)
                                            ->findOneBy(['text' => trim((string) $etiqueta->getText(), "/*+/")]);

                                    // find similar tag without '**' symbol, if exist replace in the associated collection.
                                    if (!\is_null($etiquetaSimilar)) {
                                        $nuevaEmbarazada->getOtrosAspectos()->removeElement($etiqueta); // remove the original tag with '**' and insert the new one without them.
                                        $nuevaEmbarazada->addOtrosAspecto($etiquetaSimilar);
                                    } else {
                                        // if not exist, persist a new tag without '**' symbol.
                                        $etiqueta->setText(trim((string) $etiqueta->getText(), "/*+/"));
                                        $em->persist($etiqueta);
                                    }
                                } else {
                                    continue;
                                }
                            }
                            

                            $em->persist($nuevaEmbarazada);
                            $em->flush();
                            $conn->commit();
                        } catch (Exception $exc) {
                            $conn->rollback();
                            $conn->close();

                            // return user friendly errors
                        }

                        return new Response("La embarazada fue registrada satisfactoriamente.");
                    } else {
                        $form->addError(new FormError("Error al registrar la embarazada. Rectifique los errores señalados en cada sección."));
                        return new Response($this->renderView('Embarazadas/frmCaptarEmbarazada.html.twig', ['form' => $form->createView(), 'enEdicion' => false, 'edadGestacionalActual' => $nuevaEmbarazada->getEdadGestacional()]), Response::HTTP_NOT_ACCEPTABLE);
                    }
                }

                return $this->render('Embarazadas/frmCaptarEmbarazada.html.twig', ['form' => $form->createView(), 'enEdicion' => false, 'edadGestacionalActual' => $nuevaEmbarazada->getEdadGestacional()]);
            } catch (\Exception $exc) {
                $logger->error(sprintf("[%s:%s]: %s", self::class, __FUNCTION__, $exc->getMessage()));
                return new Response("Ocurrió un error inesperado al ejecutar la operación", Response::HTTP_INTERNAL_SERVER_ERROR);
            }
        } else {
            throw $this->createNotFoundException("Recurso no encontrado");
        }
    }

检查最终结果(红框):

相关问题