令人惊讶的是,我找不到一个看似如此直接的东西的解决方案。
我的网站有一个简单的设置页面。所有设置都存储在一个简单的表中:
| 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。但这种方法存在一些问题。
block_prefixes
设置为类名(例如settings_value)。我知道这不是你应该这样做的方式,但我对我应该怎么做也毫无头绪。可能是一个集合?我应该创建一个超级类来呈现CollectionType
吗?在这种情况下,我需要知道如何应用自己的布局,因为我在设置表中为每个category
和subcategory
列渲染标题。
推进正确的方向将不胜感激:)
我今天遇到了同样的问题。这是我解决它的方式:
您将不得不调整您的代码来填写您的应用程序,以下代码只是我对如何工作的演示。不要犹豫,在评论中提出问题$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;
}
}