通过Symfony的表单生成器将新实体保存在按字段索引的一对多关联中

时间:2019-02-21 15:11:43

标签: php symfony doctrine-orm associations symfony-forms

花了很长时间我才想对标题,而我还没有写这个问题:/

在这里: 我的菜单是从实体加载的。 为了允许用户将菜单翻译成多种语言,我创建了一个Menu实体和一个LocalizedMenu通过Menu关联与ManyToOne关联的LocalizedMenu->locale实体。 / p>

this short guide之后,我为LocalizedMenu字段建立了索引。这样可以确保数据库中每个语言环境仅存在一个/** * @ORM\Entity(repositoryClass="App\Repository\MenuRepository") */ class Menu { /** * @Groups({"menu"}) * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; // ... /** * References translated menus. * @Groups({"localized_menus"}) * * @ORM\OneToMany( * targetEntity="LocalizedMenu" * ,mappedBy="parentMenu" * ,indexBy="locale" * ,cascade={"persist", "remove"} * ) * @ORM\OrderBy({"locale" = "ASC"}) */ private $localizedMenus; // ... public function getLocalizedMenu($locale) { if (!isset($this->localizedMenus[$locale])) { return new LocalizedMenu($locale, $this); } return $this->localizedMenus[$locale]; } public function addLocalizedMenu($localizedMenu): self { $this->localizedMenus[$localizedMenu->getLocale()] = $localizedMenu; return $this; } } ,并且该学说将覆盖现有语言环境。

这里是什么样子

LocalizedMenu

/** * @ORM\Entity(repositoryClass="App\Repository\LocalizedMenuRepository") */ class LocalizedMenu { public function __construct($locale, $menu) { $this->locale = $locale; $this->parentMenu = $menu; $this->parentMenu->addLocalizedMenu($this); } // region FIELDS /** * @Groups({"localized_menu", "localized_menus"}) * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @Groups({"localized_menu", "localized_menus"}) * @var $locale string * @ORM\Column( * type = "string" * ,unique = true * ) */ private $locale = ""; /** * @Groups({"localized_menu", "localized_menus"}) * @ORM\Column( * type = "string", * length = 75 * ) */ private $title = ""; /** * @Groups({"localized_menu", "localized_menus"}) * @var $description string Extra description for this menu item * @ORM\Column( * type = "text", * name = "description" * ) */ private $description = ""; /** * @Groups({"localized_menu", "localized_menus"}) * @ORM\Column( * type = "datetime", * name = "creation_date" * ) * @Assert\DateTime() */ private $creationDate; /** * @Groups({"localized_menu", "localized_menus"}) * @ORM\Column( * type = "datetime", * name = "edit_date" * ) * @Assert\DateTime() */ private $editDate; /** * @Groups({"localized_menu", "localized_menus"}) * @ORM\Column(type="text") * @Assert\NotBlank( * message = "Een menu item is een pagina die inhoud nodig heeft, vergeet dit niet" * ) */ private $content = ""; /** * @var $parentMenu Menu Parent menu for this localized menu * * @Groups({"localized_menu", "localized_parent_menu"}) * @ORM\ManyToOne( * targetEntity="Menu", * inversedBy="localizedMenus" * ) */ private $parentMenu; } 是一个包含用户翻译的菜单字段的实体:

MenyType

为了将所有内容带给用户进行编辑,我创建了一个 $builder ->add('localizedMenus', CollectionType::class, array( 'entry_type' => LocalizedMenuType::class, "entry_options" => [ "choice_locale" => $options["choice_locale"] ], 'allow_add' => true, 'allow_delete' => true, 'required' => false )) 表单:

LocalizedMenuType

还有一个 $builder ->add('title', TextType::class, array( 'label' => 'Titel', 'trim' => true )) ->add('description', TextareaType::class, array( 'label' => 'Omschrijving', 'trim' => true )) ->add('content', TextareaType::class, array( 'label' => 'Inhoud', 'trim' => true, 'attr' => array('class' => 'tinymce'), 'data' => " " )) ->add('locale', LocaleType::class, array( "choice_translation_locale" => $options["choice_locale"] )) ; 表单:

LocalizedMenu

我“认为”此逻辑是正确的,但是在使用javascript创建新的LocalizedMenu表单后,出现以下错误:

  

函数App \ Entity \ LocalizedMenu :: __ construct()的参数太少,   0传入   /Users/robbievercammen/Projects/web/base/vendor/symfony/form/Extension/Core/Type/FormType.php   在第136行,正好是2个

我如何使自己的表单与我的逻辑相符?

编辑-真正的问题

此错误消息不是真正的错误。如前所述,如果删除构造函数参数,它将把记录保存到数据库中。即,让准则使用关联将新的Menu记录与Menu记录相关联。这就是数据库中的样子:

|id| //... | 7| //...

LocalizedMenu

| id | locale | title | description | creation_date | edit_date | content | parent_menu_id | ---- | 4 | nl | Contact | Contact | 2019-02-21 14:02:47 | 2019-02-21 14:02:47 | Contact | NULL |

LocalizedMenu -> parent_menu_id

问题是$menu->getLocalizedMenus()为NULL。 由于某种原因,我的设置未为父菜单生成ID。 下次从数据库中获取菜单时,$localizedMenu -> locale返回一个空数组,因为它们未正确关联。

在我提到的guide之后,这似乎是我可以告诉理论以perf进行索引的唯一方法

1 个答案:

答案 0 :(得分:1)

您的LocalizedMenu构造函数需要两个参数-$locale$menu。当Symfony为您新提交的数据实例化新的LocalizedMenu实例时,它会直接执行new LocalizedMenu()来填充其数据。

如果您需要自定义如何为表单中的新内容/动态内容创建对象(例如,当您具有构造函数参数时),则必须在empty_data类上设置LocalizedMenuType选项。

有关更多信息,请参见https://symfony.com/doc/current/form/use_empty_data.html

您的LocalizedMenu构造函数参数之一是菜单实例。此菜单实例将需要作为必需选项传递到您的LocalizedMenuType

class LocalizedMenuType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setRequired('menu');
        $resolver->setAllowedTypes('menu', Menu::class);
        $resolver->setDefault('empty_data', function (Options $options) {
            return new LocalizedMenu($options['choice_locale'], $options['menu']);
        });
    }
}