我想创建一个设置页面,其中仅包含一个表单。如果提交表单,则只会更新设置实体,而不会创建另一个实体。目前,我实现了以下目标:
/**
* @param SettingsRepository $settingsRepository
* @return Settings
*/
public function getEntity(SettingsRepository $settingsRepository): Settings
{
$settings = $settingsRepository->find(1);
if($settings == null)
{
$settings = new Settings();
}
return $settings;
}
在SettingsController中,我调用getEntity()
方法,该方法返回新的Settings实体(如果尚未设置)或已经存在的Settings实体(如果至少设置了一次)。
但是我的解决方案非常丑陋,并且其实体ID为“ 1”,因此我正在寻找更好的解决方案。
设置控制器:
public function index(
Request $request,
SettingsRepository $settingsRepository,
FlashBagInterface $flashBag,
TranslatorInterface $translator,
SettingsService $settingsService
): Response
{
// getEntity() method above
$settings = $settingsService->getEntity($settingsRepository);
$settingsForm = $this->createForm(SettingsType::class, $settings);
$settingsForm->handleRequest($request);
if ($settingsForm->isSubmitted() && $settingsForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($settings);
$em->flush();
return $this->redirectToRoute('app_admin_settings_index');
}
return $this->render(
'admin/settings/index.html.twig',
[
'settings_form' => $settingsForm->createView(),
]
);
}
答案 0 :(得分:0)
您可以在此处使用Doctrine Embeddables。
严格来讲,不应将设置映射到实体,因为它们无法识别,也不能做到。当然,这是辩论的问题。实际上,设置对象比实体更像是值对象。阅读here了解更多信息。
因此,在这种情况下,比拥有一对一关系和所有这些模糊情况更好的情况下,您可以使用名为“设置”的简单“值对象”,将其作为“原则可嵌入”映射到数据库,就可以了。
您可以通过仅在工厂方法中创建该对象的实例,将该构造函数设为私有,防止克隆等来使该对象成为单例。通常,仅使其不可变就足够了,这意味着没有行为可以改变其状态。如果您需要对其进行突变,那么负责该方法的方法应该为其创建一个新实例。
您可以有一个像Settings::createFromArray()
这样的方法和一个叫做Settings::createDefaults()
的方法,当您新建实体时将使用该方法:始终为默认配置。
然后,您实体上的setSettings方法仅接收一个设置对象作为参数。
如果您不喜欢不变性,则还可以为Settings对象设置setter方法。