ZF2 multi-select 形式 preselect values ManyToMany

ZF2 multi-select form preselect values ManyToMany

我无法在表示多对多关系的 multiselect 表单元素中获取 preselect 值。

在我的模型中 $admin 我有正确的数据:一个包含正确 CampsTypes 的 ArrayCollection 但在表单中我无法获得 multiselect 到 preselect 正确的选项。

管理员模式

/**
 * @var ArrayCollection CampsTypes $campstypes
 *
 * @ORM\ManyToMany(targetEntity="CampsTypes", inversedBy="admins", cascade={"persist"})
 * @ORM\JoinTable(name="campstypes_admins",
 *      joinColumns={@ORM\JoinColumn(name="admins_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="campstypes_id", referencedColumnName="id")}
 *      )
 */
private $campstypes;

营地类型模型

/**
 * @var ArrayCollection Admins $admins
 *
 * @ORM\ManyToMany(targetEntity="Admins", mappedBy="campstypes", cascade={"persist"})
 */
private $admins;

然后我定义我的表单 select 元素如下

        [
            'type' => 'DoctrineModule\Form\Element\ObjectSelect',
            'name' => 'campTypes',
            'required' => false,
            'options' => [
                'object_manager' => $this->getServiceLocator()->get(EntityManager::class),
                'target_class'   => CampsTypes::class,
                'property'       => 'title',
                'label'          => 'Type de camps autorisés',
                'instructions'   => 'Ne rien sélectionner si edition d\'un super admin',

            ],
            'attributes' => [
                'class'    => '',
                'multiple' => 'multiple',
            ]
        ],

最后这是我接收表格的操作

protected function saveAdmin(Admins &$admin, &$form, &$msg)
{
    $em = $this->getEntityManager();
    /** @var CampTypesService $serviceCampTypes */
    $serviceCampTypes = $this->getServiceLocator()->get(CampTypesService::class);

    $form->bind($admin);

    if ($this->getRequest()->isPost()) {
        $data = $this->getRequest()->getPost();
        if (empty($data['password'])) {
            $form->remove('password');
        }
        $form->setData($data);
        if ($form->isValid()) {
            if (isset($data['campTypes'])) {
                $ids = $form->get('campTypes')->getValue();
                $campsTypes = new ArrayCollection($serviceCampTypes->getCampTypesByIds(array_values($ids)));
                foreach ($campsTypes as &$campsType) {
                    /** @var CampsTypes $campsType*/
                    $campsType->addAdmin($admin);
                }
                $admin->setCampTypes($campsTypes);
            }
            $em->persist($admin);
            $em->flush();
            $msg = 'Sauvegarde des données effectuée';
            return;
        }
    }

    return;
}

我正在尝试解决方案。
知道我做错了什么吗?

你有read this吗?我感觉您正在寻找 ObjectMultiCheckbox 而不是 ObjectSelect 表单元素。

来自我自己代码的例子

单个 select 的用法(用例:set/change 其他实体的默认货币)

$this->add([
    'type' => ObjectSelect::class,
    'required' => true,
    'name' => 'defaultCurrency',
    'options' => [
        'object_manager' => $this->getEntityManager(),
        'target_class'   => Currency::class,
        'property'       => 'id',
// Use these commented lines if you wish to use a Repository function ('name' => 'repositoryFunctionName')
//        'is_method'      => true,
//        'find_method'    => [
//            'name' => 'getEnabledCurrencies',
//        ],
        'display_empty_item' => true,
        'empty_item_label'   => '---',
        'label' => _('Default currency'),
        'label_attributes' => [
            'class' => '',
            'title' => _('Default currency'),
        ],
        'label_generator' => function ($targetEntity) {
            /** @var Currency $targetEntity */
            return $targetEntity->getName(); // Generates option text based on name property of Entity (Currency in this case)
        },
    ],
]);

用于多个 select(用例:add/remove(多个)角色 to/from 用户)

$this->add([
    'name' => 'roles',
    'required' => false,
    'type' => ObjectMultiCheckbox::class,
    'options' => [
        'object_manager' => $this->getEntityManager(),
        'target_class'   => Role::class,
        'property'       => 'id',
        'display_empty_item' => true,
        'empty_item_label'   => '---',
        'label' => _('Roles'),
        'label_generator' => function ($targetEntity) {
            /** @var Role $targetEntity */
            return $targetEntity->getName();
        },
    ],
]);

附带说明:您真的应该更多地使用工厂。我看到您在整个 class 代码中使用 ServiceLocator,您可以通过工厂注入您的需求来避免这种情况。


如果你需要更多信息,我建议你也看看我过去的一堆问题。我有很多,开始类似于你正在寻找的东西。我自己设法解决了其中的一些问题,并试图深入描述解决方案。

所以我成功了!

基本上我的主要问题是我没有对表单的字段名称使用正确的 Doctrine 命名约定。

所以我不得不将我的数据库逆向工程为原则实体,以便与我所做的比较以了解它在哪里不起作用。 并且还要在两端设置模型(admin 中的 camptype 和 camptypse 中的管理员)以使整个 shabang 工作。

这是工作 类 :

管理表单:

[
    'type' => ObjectSelect::class,
    'name' => 'campstypes',
    'required' => false,
    'options' => [
        'object_manager' => $this->getServiceLocator()->get(EntityManager::class),
        'target_class'   => CampsTypes::class,
        'property'       => 'title',
        'label'          => 'Type de camps autorisés',
        'instructions'   => 'Ne rien sélectionner si edition d\'un super admin',

    ],
    'attributes' => [
        'class'    => '',
        'multiple' => 'multiple',
    ]
],

管理员控制器:

protected function saveAdmin(Admins &$admin, &$form, &$msg)
{
    $em = $this->getEntityManager();
    /** @var CampTypesService $serviceCampTypes */
    $serviceCampTypes = $this->getServiceLocator()->get(CampTypesService::class);

    $form->bind($admin);

    if ($this->getRequest()->isPost()) {
        $data = $this->getRequest()->getPost();
        if (empty($data['password'])) {
            $form->remove('password');
        }
        $form->setData($data);
        if ($form->isValid()) {
            if (isset($data['campstypes'])) {
                $ids = $form->get('campstypes')->getValue();
                $campsTypes = new ArrayCollection($serviceCampTypes->getCampTypesByIds(array_values($ids)));
                foreach ($campsTypes as &$campsType) {
                    /** @var CampsTypes $campsType*/
                    $campsType->addAdmin($admin);
                }
                $admin->setCampstypes($campsTypes);
            }
            $em->persist($admin);
            $em->flush();
            $msg = 'Sauvegarde des données effectuée';
            return;
        }
    }

    return;
}

因此,通过正确重命名我的表单和模型的字段并在关系的两端模型中设置数据,我让它工作了。