ZF2多选表单预选值ManyToMany

时间:2017-11-28 15:13:54

标签: php forms zend-framework2 many-to-many multi-select

我无法预先选择表示多对多关系的多选表单元素中的值。

在我的模型$admin中,我有正确的数据:一个包含正确CampsTypes的ArrayCollection,但是我不能通过多选来预选合适的选项。

管理员模型

/**
 * @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;

CampsType模型

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

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

        [
            '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;
}

我没有尝试解决问题 知道我做错了吗?

2 个答案:

答案 0 :(得分:0)

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

我自己的代码中的示例

单个选择的用法(用例:设置/更改其他实体的默认货币)

$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)
        },
    ],
]);

用于多个选择(用例:向用户添加/删除(多个)角色)

$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();
        },
    ],
]);

作为旁注:你应该更多地使用工厂。我看到你在整个课程代码中使用ServiceLocator,你可以通过工厂注入你的需求来避免这种情况。

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

答案 1 :(得分:0)

所以我做到了!

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

因此,我不得不将我的数据库逆向工程化为学说实体,以便与我所做的相比较,以了解它不起作用的地方。 并且还要在两端设置模型(管理员中的管理员和管理员中的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;
}

因此,通过正确地重命名我的表单和模型的字段,并在关系的两个结束模型中设置数据,我得到了它。

相关问题