同一实体类型的多个表单

问题描述 投票:0回答:1

令人惊讶的是,我找不到一个看似如此直接的东西的解决方案。

我的网站有一个简单的设置页面。所有设置都存储在一个简单的表中:

| id | name                | label                                             | type   | value                 | is_user_created | is_editable | edit_date           | original_name | category         | file                 | subcategory |
+----+---------------------+---------------------------------------------------+--------+-----------------------+-----------------+-------------+---------------------+---------------+------------------+----------------------+-------------+
| 21 | index_header_large  | Large header for index page                       | bool   | true                  |               0 |           1 | 2018-09-17 13:22:20 |               | Layout           |                      | Heading     |
| 25 | website_title       | Short title                                       | string | My website            |               0 |           1 | 2018-09-17 13:22:20 |               | Details website  |                      |             |
| 26 | website_owner       | Name of the owner                                 | string | Not specified         |               0 |           1 | 2018-09-17 13:22:20 |               | Gegevens website |                      |             |
+----+---------------------+---------------------------------------------------+--------+-----------------------+-----------------+-------------+---------------------+---------------+------------------+----------------------+-------------+

设置表有一个名为type的列。我用它来生成一个FormType,它具有表单必须呈现的值类型的正确字段/断言。

它们看起来非常相似,这种类型的字符串类型:

class SettingsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /* @var $entity \App\Entity\Setting */
        $entity=$builder->getData();
        $builder
            ->add('value', TextType::class, array(
                'label'             => $entity->getLabel(),
                'trim'              => true,
                'translation_domain' => 'app'
            ));
        ;
    }
}

在控制器中,我获取设置并迭代它们以创建表单

    $settings = $repSettings->findAllOrderedByCategory();

    $settingForms = [];
    /* @var $setting Setting */
    foreach ($settings as $setting) {
        if ($setting->getType() === 'bool') {
            array_push($settingForms, $this->createForm(SettingsBoolType::class, $setting, array(
                'action' => $this->generateUrl(
                    'admin_set_setting_value',
                    array(
                        "_locale" => $request->getLocale(),
                        "_id" => $setting->getId()
                    )
                )
            ))->createView());
        } else if ($setting->getType() === 'file') {
            array_push($settingForms, $this->createForm(SettingsFileType::class, $setting, array(
                'action' => $this->generateUrl(
                    'admin_set_setting_file',
                    array(
                        "_locale" => $request->getLocale(),
                        "_id" => $setting->getId())
                )
            ))->createView());
        } else {
            array_push($settingForms, $this->createForm(SettingsType::class, $setting, array(
                'action' => $this->generateUrl(
                    'admin_set_setting_value',
                    array(
                        "_locale" => $request->getLocale(),
                        "_id" => $setting->getId())
                )
            ))->createView());
        }
    }

    return $this->render('admin/manage_settings.html.twig', array_merge(
        array(
            'settingForms'      => $settingForms,
        )
    ));

好到目前为止,表单呈现和工作,因为每个表单在操作URL中都设置了唯一的ID。但这种方法存在一些问题。

  • 提交的值错误:它似乎适用于字符串值表单,但有时布尔值表单会为错误的设置提交值。
  • 重复ID:每个表单的block_prefixes设置为类名(例如settings_value)。

我知道这不是你应该这样做的方式,但我对我应该怎么做也毫无头绪。可能是一个集合?我应该创建一个超级类来呈现CollectionType吗?在这种情况下,我需要知道如何应用自己的布局,因为我在设置表中为每个categorysubcategory列渲染标题。

推进正确的方向将不胜感激:)

php symfony twig symfony-forms
1个回答
1
投票

我今天遇到了同样的问题。这是我解决它的方式:

您将不得不调整您的代码来填写您的应用程序,以下代码只是我对如何工作的演示。不要犹豫,在评论中提出问题$data只是一个包含一些Setting对象的数组。为了加快速度,我在Settings :: type属性中使用了symfony内置类型。您可以在ExtendedFieldCollectionType中编写适配器代码

<?php

namespace App\Controller;

use App\Model\Setting;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class DemoController extends AbstractController
{
    /**
     * @Route(name="demo_demo", path="/demo")
     * @Template()
     * @param Request $request
     * @return array
     */
    public function demo(Request $request)
    {
        $data = [
            new Setting('count', NumberType::class, 0.5),
            new Setting('text', TextType::class,'sample text'),
            new Setting('date', DateType::class, new \DateTime())
        ];

        $form = $this->createForm('App\Form\ExtendedFieldCollectionType', $data);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // ...
        }

        return [
            'form' => $form->createView()
        ];
    }
}

表格类型:

<?php

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ExtendedFieldCollectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $form = $event->getForm();
            $data = $event->getData();

            foreach ($data as $name => $value) {
                $form->add($value->id, $value->type, [
                    'property_path' => '[' . $name . '].value', // the value property is my setting value
                ]);
            }
        });
    }
}

我使用的模型

<?php

namespace App\Model;


class Setting
{
    public $id;
    public $type;
    public $value;

    /**
     * ProjectField constructor.
     * @param $id
     * @param $type
     * @param $value
     */
    public function __construct($id, $type, $value)
    {
        $this->id = $id;
        $this->type = $type;
        $this->value = $value;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.