Несколько форм для одного типа объекта - PullRequest
0 голосов
/ 18 сентября 2018

Удивительно, что я не могу найти решение для чего-то, что кажется таким простым.

Мой сайт имеет простую страницу настроек.Все настройки хранятся в простой таблице:

| 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-адрес.Но у этого метода есть некоторые проблемы.

  • Отправлены неверные значения: Кажется, он работает для форм строковых значений, но иногда форма логических значений представляет значение для неправильной настройки.

  • Дубликаты идентификаторов: block_prefixes для каждой формы задается имя класса (например, settings_value).

Я знаю, что это не таккак вы должны это сделать, но я не знаю, как мне следует.Коллекция может быть?Должен ли я создать super класс для рендеринга CollectionType?В этом случае мне нужно знать, как я могу применить свой собственный макет, потому что я отображаю заголовки для каждого столбца category и subcategory в таблице настроек.

Будет приветствоваться толчок в правильном направлении:)

1 Ответ

0 голосов
/ 18 сентября 2018

Я столкнулся с той же проблемой сегодня.Вот как я это решил:

Вам придется адаптировать свой код, чтобы заполнить ваше приложение, следующий код - просто демонстрация, которую я сделал о том, как все работает.Не стесняйтесь задавать вопросы в комментариях. $data - это просто массив с некоторыми Setting объектами.Чтобы ускориться, я использовал встроенные типы Symfony для свойства Settings :: type.Вы можете свободно кодировать адаптер в 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;
    }
}
...