我无法为似乎如此直接的事情找到解决方案,这真是令人惊讶。
我的网站有一个简单的设置页面。所有设置都存储在一个简单的表中:
| 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)。
我知道这不是您应该采取的方式,但是我对应该采取的方式一无所知。可能是收藏吗?我应该创建一个 super 类以呈现CollectionType
吗?在那种情况下,我需要知道如何应用自己的布局,因为我为设置表中的每个category
和subcategory
列渲染了标题。
朝正确方向的推动将不胜感激:)
答案 0 :(得分:1)
我今天遇到了同样的问题。这是我解决的方法:
您将不得不修改您的代码以填写您的应用程序,以下代码只是我所做的关于事情如何工作的演示。
不要犹豫,在评论中提问
$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;
}
}