在Symfony 4中创建单例实体的最佳方法是什么?

时间:2018-07-18 12:34:17

标签: symfony doctrine-orm entity symfony4

我想创建一个设置页面,其中仅包含一个表单。如果提交表单,则只会更新设置实体,而不会创建另一个实体。目前,我实现了以下目标:

 /**
 * @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(),
        ]
    );
}

1 个答案:

答案 0 :(得分:0)

您可以在此处使用Doctrine Embeddables

严格来讲,不应将设置映射到实体,因为它们无法识别,也不能做到。当然,这是辩论的问题。实际上,设置对象比实体更像是值对象。阅读here了解更多信息。

因此,在这种情况下,比拥有一对一关系和所有这些模糊情况更好的情况下,您可以使用名为“设置”的简单“值对象”,将其作为“原则可嵌入”映射到数据库,就可以了。

您可以通过仅在工厂方法中创建该对象的实例,将该构造函数设为私有,防止克隆等来使该对象成为单例。通常,仅使其不可变就足够了,这意味着没有行为可以改变其状态。如果您需要对其进行突变,那么负责该方法的方法应该为其创建一个新实例。

您可以有一个像Settings::createFromArray()这样的方法和一个叫做Settings::createDefaults()的方法,当您新建实体时将使用该方法:始终为默认配置。

然后,您实体上的setSettings方法仅接收一个设置对象作为参数。

如果您不喜欢不变性,则还可以为Settings对象设置setter方法。